• Ephera@lemmy.ml
    link
    fedilink
    English
    arrow-up
    8
    ·
    2 days ago

    “I think proc macros are a really big superpower for Rust.”

    Yeah, been working on a framework and proc-macros are really useful to simplify the API.

    For example, previously I needed users to define a struct and then an impl block with a function inside. Well, and they need to do that a lot, so it was genuinely a bit of a pain to write out, but it also made the code feel more complex than it really was.

    Now I’ve got an annotation, which you can slap onto a function and then it generates the struct from the function parameters and puts the function into the impl block.
    And while you do need to be aware that the function parameters will be put into a struct and therefore you want owned parameters, all-in-all it still feels really nice to just delete dozens of boilerplate lines and an indentation level in the codebases where I’ve introduced it.

    • Matt@lemmy.ml
      link
      fedilink
      arrow-up
      2
      ·
      14 hours ago

      Unfortunately, proc-macros need to be in a separate crate. It’d be great if we don’t have to do that.

      • Ephera@lemmy.ml
        link
        fedilink
        English
        arrow-up
        1
        ·
        13 hours ago

        Yeah, as I’m implementing this, I’m also now noticing how problematic that crate split is.

        If you want to generate code which uses (non-generated) types that your crate provides in its public API, you have to re-export the macro from a separate crate that also re-exports the types.
        That in itself is clunky, but it’s just complexity for the implementer, not the user, so it’s fine.

        But where it stops being fine is that this means you cannot easily provide a usage example in the macro’s documentation.
        If you try to use it like normal, it has to generate code referring to your API crate, which will not be defined in your macro crate, so the documentation test won’t compile.

        So, basically your choices are:

        • Do some hacky horseshit, where you try to re-define the public API in the usage example.
        • Provide a usage example, which is not checked for compile errors.
        • Provide a usage example on the module that re-exports the macro rather than on the macro itself.
        • Don’t provide a usage example.

        And yeah… if you’ve coded Rust for long enough, you will recognize these patterns of bad/missing usage examples, which is particularly problematic, because proc-macros are rarely terribly obvious to use. Really hope they can fix this sooner rather than later.
        As far as I can tell, it would even be a valid fix, if editors and such consistently showed the documentation declared on top of the re-export, then you could write out your usage example there.