Description
cargo build
on the following code produces an ICE (just cargo check
doesn’t ICE)
#![feature(unboxed_closures)]
trait SomeTrait<'a> {
type Associated;
}
fn give_me_ice<T>() {
callee::<fn(&()) -> <T as SomeTrait<'_>>::Associated>();
}
fn callee<T: Fn<(&'static (),)>>() {
println!(
"{}",
std::any::type_name::<<T as FnOnce<(&'static (),)>>::Output>()
);
}
fn main() {
give_me_ice::<()>();
}
Compiling playground v0.0.1 (/playground)
error: internal compiler error: compiler/rustc_traits/src/normalize_erasing_regions.rs:54:32: could not fully normalize `fn() -> &'static str {std::any::type_name::<<for<'r> fn(&'r ()) -> <() as SomeTrait<'r>>::Associated as std::ops::FnOnce<(&(),)>>::Output>}`
thread 'rustc' panicked at 'Box<Any>', /rustc/3e99439f4dacc8ba0d2ca48d221694362d587927/library/std/src/panic.rs:59:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
note: the compiler unexpectedly panicked. this is a bug.
note: we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md
note: rustc 1.54.0-nightly (3e99439f4 2021-05-17) running on x86_64-unknown-linux-gnu
note: compiler flags: -C embed-bitcode=no -C codegen-units=1 -C debuginfo=2 --crate-type bin
note: some of the compiler flags provided by cargo are hidden
query stack during panic:
#0 [normalize_generic_arg_after_erasing_regions] normalizing `fn() -> &'static str {std::any::type_name::<<for<'r> fn(&'r ()) -> <() as SomeTrait<'r>>::Associated as std::ops::FnOnce<(&(),)>>::Output>}`
#1 [collect_and_partition_mono_items] collect_and_partition_mono_items
end of query stack
error: aborting due to previous error
error: could not compile `playground`
To learn more, run the command again with --verbose.
Possibly, this bug can also lead to unsoundness in some way. (I haven’t fully explored that [yet].) Notably, Box<dyn Fn…>
doesn’t come with the same problem:
#![feature(unboxed_closures)]
trait SomeTrait<'a> {
type Associated;
}
fn give_me_ice<T>() {
callee::<Box<dyn Fn(&()) -> <T as SomeTrait<'_>>::Associated>>();
}
fn callee<T: Fn<(&'static (),)>>() {
println!(
"{}",
std::any::type_name::<<T as FnOnce<(&'static (),)>>::Output>()
);
}
fn main() {
give_me_ice::<()>();
}
Compiling playground v0.0.1 (/playground)
error[E0277]: the trait bound `T: SomeTrait<'_>` is not satisfied
--> src/main.rs:8:5
|
8 | callee::<Box<dyn Fn(&()) -> <T as SomeTrait<'_>>::Associated>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `SomeTrait<'_>` is not implemented for `T`
...
11 | fn callee<T: Fn<(&'static (),)>>() {
| ------------------ required by this bound in `callee`
|
= note: required because of the requirements on the impl of `Fn<(&'static (),)>` for `Box<dyn for<'r> Fn(&'r ()) -> <T as SomeTrait<'_>>::Associated>`
help: consider restricting type parameter `T`
|
7 | fn give_me_ice<T: SomeTrait<'_>>() {
| ^^^^^^^^^^^^^^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.
error: could not compile `playground`
To learn more, run the command again with --verbose.
I would’ve expected a similar error message for the fn…
case as well.
(Further, note that the way things currently stand, the type Box<dyn Fn(&()) -> <T as SomeTrait<'_>>::Associated>
itself is not leading to any error. It’s only the call to callee
which has an Fn<…>
bound. The error also successfully appears if callee
has a higher-ranked Fn<…>
bound and/or is not actually called but just instantiated with the type argument, here’s a playground doing both.)
@rustbot label requires-nightly, F-unboxed_closures, A-traits, A-typesystem, A-associated-items