Closed
Description
trait ATC<'a> {
type Type: Sized;
}
trait WithDefault: for<'a> ATC<'a> {
fn with_default<F: for<'a> Fn(<Self as ATC<'a>>::Type)>(f: F);
}
fn call<'b, T: for<'a> ATC<'a>, F: for<'a> Fn(<T as ATC<'a>>::Type)>(
f: F,
x: <T as ATC<'b>>::Type,
) {
f(x);
}
impl<'a> ATC<'a> for () {
type Type = Self;
}
impl WithDefault for () {
fn with_default<F: for<'a> Fn(<Self as ATC<'a>>::Type)>(f: F) {
// Errors with a bogus type mismatch.
//f(());
// Going through another generic function works fine.
call(f, ());
}
}
fn main() {
// <()>::with_default(|_| {});
}
As you can see, calling f
directly doesn't instantiate the HRTB (even though it needs to AFAIK) or if it does it doesn't normalize the resulting bound, whereas going through call
normalizes the instantiated argument types of call
, while call
's definition can be type-checked as-is.
EDIT: you can also get an ICE by uncommenting the use in main
:
error: internal compiler error: librustc/traits/trans/mod.rs:68: Encountered error `OutputTypeParameterMismatch(
Binder(<[closure@src/main.rs:30:24: 30:30] as std::ops::Fn<(<() as ATC<'_>>::Type,)>>),
Binder(<[closure@src/main.rs:30:24: 30:30] as std::ops::Fn<((),)>>),
Sorts(ExpectedFound { expected: (), found: <() as ATC<'_>>::Type })
)` selecting `Binder(<[closure@src/main.rs:30:24: 30:30] as std::ops::Fn<((),)>>)` during trans
cc @nikomatsakis (this might be a duplicate)