Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fails with associated functions on types #22

Open
korrat opened this issue Aug 7, 2024 · 0 comments
Open

Fails with associated functions on types #22

korrat opened this issue Aug 7, 2024 · 0 comments

Comments

@korrat
Copy link

korrat commented Aug 7, 2024

When using momo on an associated function (without a self parameter), the generated code fails, since the call to the non-generic function is missing the Self:: prefix.

Example code demonstrating the problem:

struct Test {
    inner: Box<str>,
}

#[momo::momo]
fn new_freestanding(inner: impl AsRef<str>) -> Test {
    let inner = inner.into();
    Test { inner }
}

impl Test {
    #[momo::momo]
    fn new(inner: impl AsRef<str>) -> Self {
        let inner = inner.into();
        Self { inner }
    }
}

And the corresponding expansion:

Possible alternatives:

  1. Make #[momo] work on impl blocks, transforming all functions. IMO, this would cover all use cases, but I may have missed some edge cases. Might also be a bigger rewrite.
  2. Detect usage of Self type in function (signature) and generate calls with Self::. While this would cover the described problem, it is only a best-effort heuristic and may miss cases.
  3. Generate an inner function. AFAICT, this is the common way to write this manually. However, it also runs into issues with the Self type, but in the opposite direction. We would need to spell out Self as the full type everywhere. It also won't work with generic structs, as the inner function cannot reference the generics from the type/impl block.
  4. Generate a nested closure and convert to a function pointer. This requires a bit of setup but can be made to be equivalent to the nested function code:
#[derive(Debug)]
struct Test {
    inner: Box<str>,
}

impl Test {
    fn new(inner: impl AsRef<str>) -> Self {
        let new_inner: fn(&str) -> Self = {
            #[inline(never)]
            |inner: &str| {
                let inner = inner.into();
                Self { inner }
            }
        };

        new_inner(inner.as_ref())
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant