danielhenrymantilla / nougat.rs

(lifetime) GATs on stable Rust
https://docs.rs/nougat
Apache License 2.0
53 stars 6 forks source link

Extend macro to append additional `use`s. #9

Closed azriel91 closed 2 years ago

azriel91 commented 2 years ago

Proof of concept implementation of #8.

I haven't tested both exports / imports, and it should be possible to support renames.

azriel91 commented 2 years ago

Wasn't obvious how to do renames, so given a library exports this trait:

// publishing crate
#[gat]
pub trait LendingIterator {
    type Item<'next> where Self : 'next;
    // ..
}

// LendingIterator and LendingIteratorඞData are exported

then a consumer crate can rename the import like so:

// either of:
#[gat(Item)]
use library::LendingIterator as LendingIteratorRenamed;
#[gat(Item)]
use library::{LendingIterator as LendingIteratorRenamed}; // works with braces too

// produces:
use library::LendingIterator as LendingIteratorRenamed;
use library::{LendingIteratorඞData as LendingIteratorRenamedඞData};

It also works with multiple lent items -- added that in tests

danielhenrymantilla commented 2 years ago

By the way, I had also considered a complementary / additional approach, to optionally get the user not to have to provide the (g) associated types, using an internal ad-hoc generated macro that would take care of remembering that info. But since properly scoped pub macros are not really a thing, my approach would break if eponymous #[gat]-annotated pub traits ended up defined in the same crate 😬…

But for the sake of it, here is what the idea was about:

#[gat]
trait LendingIterator {

would, on top of the LendingIterator trait (and friends), generate a LendingIterator! "import assistant" macro.

Then,

#[gat]
use …::LendingIterator;

would become:

…::LendingIterator! {
    use …::LendingIterator
}

which, in turn, would become:

#[gat(Item, …)] // <- still uses the logic of this very PR
use …::LendingIterator;

Thoughts?

azriel91 commented 2 years ago

Thoughts?

I certainly find it valuable to reduce the effort on the users' end; I actually misinterpreted your message the first time and thought the #[gat] on top of the impl Trait for .. would magically figure out how to use path::to::TraitඞData -- which would be exciting, but at that point we can't resolve the module path :sweat_smile:.

this would also need to resolve the path to #[gat]

I think this part may be able to be resolved, since #[gat] is already in the calling scope; the part that I think of a solution for is:

properly scoped pub macros are not really a thing