-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Surprising type inference on method call without explicit turbo-fish #49996
Comments
It’s not a bug.
|
Thanks for the reply!
I don't necessarily want to create a collection. I don't understand why it should matter that
I assume you're referring to the fact that I release I don't use turbofish notation to pass a type hint to the fn bar<'a, I>(self, collection: &'a I) where for <'b> &'b I: IntoIterator<Item= &'b &'a Self::Baz> {
let collection = collection.into_iter().map(|b| &b.delegate).collect::<Vec<&<T as FooMut>::Baz>>();
self.delegate.bar(&collection)
} (Play) If I then also add the exact same turbofish to the fn bar<'a, I>(self, collection: &'a I) where for <'b> &'b I: IntoIterator<Item= &'b &'a Self::Baz> {
let collection = collection.into_iter().map(|b| &b.delegate).collect::<Vec<&<T as FooMut>::Baz>>();
self.delegate.bar::<Vec<&<T as FooMut>::Baz>>(&collection)
} (Play) I guess my question boils down to the following: why does that turbofish on the |
Well, the
(I do wonder if the "StreamingIterator" idea that would be enabled by generic associated types could support an adaptor that puts each value it receives from the wrapped iterator into an
|
Thanks @ExpHP, I understand now why my original approach does not work. I still don't quite understand why this version compiles: fn bar<'a, I>(self, collection: &'a I) where for <'b> &'b I: IntoIterator<Item= &'b &'a Self::Baz> {
let collection = collection.into_iter().map(|b| &b.delegate).collect::<Vec<&<T as FooMut>::Baz>>();
self.delegate.bar::<Vec<&<T as FooMut>::Baz>>(&collection)
} But this version does not: fn bar<'a, I>(self, collection: &'a I) where for <'b> &'b I: IntoIterator<Item= &'b &'a Self::Baz> {
let collection = collection.into_iter().map(|b| &b.delegate).collect::<Vec<&<T as FooMut>::Baz>>();
self.delegate.bar(&collection)
} However, this did allow me to work around my current problem. |
Okay, that last example is super weird. There is a known issue that type inference can be very aggressive with What's really strange is that even just the following turbofish suffices: fn bar<'a, I>(self, collection: &'a I) where for <'b> &'b I: IntoIterator<Item= &'b &'a Self::Baz> {
// same as both examples in above post
let collection = collection.into_iter().map(|b| &b.delegate).collect::<Vec<&<T as FooMut>::Baz>>();
// shorter turbofish (infer the element type)
self.delegate.bar::<Vec<_>>(&collection)
} I guess just seeing |
Should I reopen? I can also open a fresh issue that cuts out the intertwined |
IMO nothing wrong with just reopening for now. I think the original post is fine. |
It seems (I might be wrong) that type inference is using If possible, it might be easier to write
This would also let a Map (over a referenced Vec, say) through. |
play for the above suggestion. |
Thanks a lot for the suggestion @vitalyd! I ended up going with the following to solve my API's needs: fn bar<'a, I, B>(self, collection: I) where I: IntoIterator<Item=B>, B: Borrow<&'a Self::Baz> This seems to give me good range of valid values (the most notable for me: |
@RSSchermer, nice touch with I’d still love for someone to explain type inference’s behavior here. |
Please excuse the lack of specificity in the title, it reflects my lack of understanding what is going on here.
Here's a distilled example of what I'm going for:
(Play)
This fails to compile (on stable and nightly) with:
I played around a bit and found that changing the
bar
implementation to the following does compile:(Play)
But only with the turbo-fish on the call to
self.delegate.bar
; if I remove the turbo-fish it once again fails to compile:(Play)
This surprised me. From the error it seems like the compiler infers the type-parameter on the call to the delegate to be the same as the type parameter on the outer (delegating) method. I am not completely sure if this is a bug or intended behavior. If this isn't a bug I was hoping someone would perhaps be able to give me some insight into the what and why and a possible work-around.
While collecting into a
Vec
works as a workaround for now, I would really like to avoid having to allocate. I'm assuming that I might be able to make the original example work if I can work out a type for a turbo-fish there, butstd::iter::Map
seems to take the concrete type of its closure as a type parameter and I cannot figure out how to represent that in the turbo-fish type (if that's possible at all).The text was updated successfully, but these errors were encountered: