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

Support use of non-repeating tokens in repeating blocks #7

Closed
sfackler opened this issue Oct 9, 2016 · 6 comments
Closed

Support use of non-repeating tokens in repeating blocks #7

sfackler opened this issue Oct 9, 2016 · 6 comments

Comments

@sfackler
Copy link

sfackler commented Oct 9, 2016

From https://github.com/dtolnay/quote/releases/tag/0.3.0:

Cannot mix repeating and non-repeating tokens at the same level. If #a is repeating (like a Vec) and #b is not, then quote! { #(#a #b)* } will not work. Ideally it would insert the same #b for each #a the way macro_rules! does but I have not figured this out yet. For now you can explicitly repeat b using std::iter::repeat.

Filing as an issue so I'll know when it's fixed :)

@dtolnay
Copy link
Owner

dtolnay commented Nov 24, 2016

I think I can make this work with specialization. Basically specialize something which is the identity function for anything that is already iterable, and iter::repeat for everything else.

@dtolnay
Copy link
Owner

dtolnay commented Nov 27, 2016

Hmm the hard part is what happens if everything in a repeating block is non-repeating, you don't want it to iter::repeat everything and run forever.

@dtolnay
Copy link
Owner

dtolnay commented Dec 2, 2016

After three ICEs (#33017, #35676, #38091) and two hacky workarounds (diamond pattern and default type) I think I am one lifetime puzzler away from getting this working. @sfackler can you give me a hand?

In vastly simplified form it looks like this. There is a trait Iterate which creates a Repetition over any value T (shown here) or an IntoIterator (not shown).

#![feature(specialization)]

struct Repeat<T>(T);

trait Iterate<'a> {
    type Ty: Repetition<'a>;
    fn iterate(self) -> Self::Ty;
}

impl<'a, T: 'a> Iterate<'a> for T {
    type Ty = Repeat<T>;
    fn iterate(self) -> Self::Ty { unimplemented!() }
}

trait Repetition<'a> {
    type Item;
    fn next(&'a mut self) -> Self::Item;
}

impl<'a, T: 'a> Repetition<'a> for Repeat<T> {
    type Item = &'a T;
    fn next(&'a mut self) -> Self::Item { &self.0 }
}

fn main() {
    let mut x = Iterate::iterate(0);
    Repetition::next(&mut x);
    Repetition::next(&mut x);
}

The problem is if you change type Ty = Repeat<T> to default type Ty = Repeat<T>. Then neither Repetition::next call is allowed.

Adding a second lifetime parameter to Iterate, the first call to Repetition::next is allowed but the second is not (though again, both are allowed with type instead of default type).

trait Iterate<'a, 'b: 'a> {
    type Ty: Repetition<'a> + 'b;
    fn iterate(self) -> Self::Ty;
}

impl<'a, 'b: 'a, T: 'b> Iterate<'a, 'b> for T {
    default type Ty = Repeat<T>;
    fn iterate(self) -> Self::Ty { unimplemented!() }
}

What is the right bound for Iterate::Ty so I can make as many Repetition::next calls as I want, like I can with the concrete type Repeat<T>?

@dtolnay
Copy link
Owner

dtolnay commented Dec 2, 2016

These traits look a lot like fst::IntoStreamer and fst::Streamer, I will look at how those work.

@dtolnay
Copy link
Owner

dtolnay commented Jan 28, 2019

Closing as an acknowledged limitation because I don't plan to pursue this. If anyone comes up with a PR to make this work better, I would be willing to consider it.

@dtolnay dtolnay closed this as completed Jan 28, 2019
@dtolnay
Copy link
Owner

dtolnay commented Jan 28, 2019

Added an indication of the limitation in the docs: f81fdb4.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants