fn bar<T: Send>(t: T) {}
fn foo(t: impl Send) { }
fn main() {
let b = bar::<i32>(10);
let f = foo::<i32>(10); // <-- Error here
}
One would think that impl Send
is just sugar for the generic. Why doesn't this work?
fn bar<T: Send>(t: T) {}
fn foo(t: impl Send) { }
fn main() {
let b = bar::<i32>(10);
let f = foo::<i32>(10); // <-- Error here
}
One would think that impl Send
is just sugar for the generic. Why doesn't this work?
I think this discussion from the time the current design was stabilized highlights some of the thoughts behind the current design, and possible alternatives:
I have two answers:
fn qux(x: impl Foo<impl Bar, Output = impl Zoo>)
, it's no longer obvious to me that turning all these into generic parameters that can be turbofished is a good idea, and while one could make a rule for the order in which they'd appear (@WaffleLapkin made a better example of this.), I'm not sure any such order is necessarily intuitive to the caller.fn foo<T>(x: impl FnOnce(T) -> T)
, for example -- being able to call that as foo::<i32>(|x| x + 1)
without being forced to put a _
in (like you would for fn foo<T, F: impl FnOnce(T) -> T>(x: F)
) improves the experience for the caller. And thus using APITs for things where it's common to not care about the exact type (like closures and iterators) provides a nice bonus by not having the implicit generic in the turbofish list.This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.