The following code triggers an ICE.
Code
#![feature(generic_associated_types)]
pub trait Iter {
type Item<'a> where Self: 'a;
fn next<'a>(&'a mut self) -> Option<Self::Item<'a>>;
fn for_each<F>(mut self, mut f: F)
where Self: Sized, F: for<'a> FnMut(Self::Item<'a>)
{
while let Some(item) = self.next() {
f(item);
}
}
}
pub struct Windows<T> {
items: Vec<T>,
start: usize,
len: usize,
}
impl<T> Windows<T> {
pub fn new(items: Vec<T>, len: usize) -> Self {
Self { items, start: 0, len }
}
}
impl<T> Iter for Windows<T> {
type Item<'a> where T: 'a = &'a mut [T];
fn next<'a>(&'a mut self) -> Option<Self::Item<'a>> {
let slice = self.items.get_mut(self.start..self.start + self.len)?;
self.start += 1;
Some(slice)
}
}
fn main() {
Windows::new(vec![1, 2, 3, 4, 5], 3)
.for_each(|slice| println!("{:?}", slice));
}
Playground version
This example can no doubt be minimised further, but it should be obvious what I'm attempting to do and why. This would be, I assume, a fairly common use-case for GATs and are likely to be essential if GATs are ever to be integrated into Iterator.
Meta
rustc --version --verbose:
rustc 1.48.0-nightly (d006f5734 2020-08-28)
Error output
error: internal compiler error: src/librustc_trait_selection/traits/codegen/mod.rs:75:17: Encountered error `OutputTypeParameterMismatch(Binder(<[closure@gats.rs:41:19: 41:50] as std::ops::FnMut<(<Windows<i32> as Iter>::Item<'_>,)>>), Binder(<[closure@gats.rs:41:19: 41:50] as std::ops::FnMut<(&mut [i32],)>>), Sorts(ExpectedFound { expected: &mut [i32], found: <Windows<i32> as Iter>::Item<'_> }))` selecting `Binder(<[closure@gats.rs:41:19: 41:50] as std::ops::FnMut<(&mut [i32],)>>)` during codegen
thread 'rustc' panicked at 'Box<Any>', src/librustc_errors/lib.rs:918:9
Backtrace
stack backtrace:
0: std::panicking::begin_panic
1: rustc_errors::HandlerInner::bug
2: rustc_errors::Handler::bug
3: rustc_middle::util::bug::opt_span_bug_fmt::{{closure}}
4: rustc_middle::ty::context::tls::with_opt::{{closure}}
5: rustc_middle::ty::context::tls::with_opt
6: rustc_middle::util::bug::opt_span_bug_fmt
7: rustc_middle::util::bug::bug_fmt
8: rustc_infer::infer::InferCtxtBuilder::enter
9: rustc_trait_selection::traits::codegen::codegen_fulfill_obligation
10: rustc_middle::ty::query::<impl rustc_query_system::query::config::QueryAccessors<rustc_middle::ty::context::TyCtxt> for rustc_middle::ty::query::queries::codegen_fulfill_obligation>::compute
11: rustc_query_system::dep_graph::graph::DepGraph<K>::with_task_impl
12: rustc_data_structures::stack::ensure_sufficient_stack
13: rustc_query_system::query::plumbing::get_query_impl
14: rustc_ty::instance::inner_resolve_instance
15: rustc_ty::instance::resolve_instance
16: rustc_middle::ty::query::<impl rustc_query_system::query::config::QueryAccessors<rustc_middle::ty::context::TyCtxt> for rustc_middle::ty::query::queries::resolve_instance>::compute
17: rustc_query_system::dep_graph::graph::DepGraph<K>::with_task_impl
18: rustc_data_structures::stack::ensure_sufficient_stack
19: rustc_query_system::query::plumbing::get_query_impl
20: rustc_middle::ty::instance::Instance::resolve_opt_const_arg
21: rustc_middle::ty::instance::Instance::resolve
22: <rustc_mir::monomorphize::collector::MirNeighborCollector as rustc_middle::mir::visit::Visitor>::visit_terminator
23: rustc_mir::monomorphize::collector::collect_neighbours
24: rustc_mir::monomorphize::collector::collect_items_rec
25: rustc_mir::monomorphize::collector::collect_items_rec
26: rustc_session::utils::<impl rustc_session::session::Session>::time
27: rustc_mir::monomorphize::collector::collect_crate_mono_items
28: rustc_mir::monomorphize::partitioning::collect_and_partition_mono_items
29: rustc_middle::ty::query::<impl rustc_query_system::query::config::QueryAccessors<rustc_middle::ty::context::TyCtxt> for rustc_middle::ty::query::queries::collect_and_partition_mono_items>::compute
30: rustc_query_system::dep_graph::graph::DepGraph<K>::with_task_impl
31: rustc_data_structures::stack::ensure_sufficient_stack
32: rustc_query_system::query::plumbing::get_query_impl
33: rustc_codegen_ssa::base::codegen_crate
34: <rustc_codegen_llvm::LlvmCodegenBackend as rustc_codegen_ssa::traits::backend::CodegenBackend>::codegen_crate
35: rustc_interface::passes::QueryContext::enter
36: rustc_interface::queries::Queries::ongoing_codegen
37: rustc_interface::queries::<impl rustc_interface::interface::Compiler>::enter
38: rustc_span::with_source_map
39: rustc_interface::interface::create_compiler_and_run
40: scoped_tls::ScopedKey<T>::set
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose 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.48.0-nightly (d006f5734 2020-08-28) running on x86_64-unknown-linux-gnu
query stack during panic:
#0 [codegen_fulfill_obligation] checking if `std::ops::FnMut` fulfills its obligations
#1 [resolve_instance] resolving instance `<[closure@gats.rs:41:19: 41:50] as std::ops::FnMut<(&mut [i32],)>>::call_mut`
#2 [collect_and_partition_mono_items] collect_and_partition_mono_items
end of query stack
error: aborting due to previous error; 1 warning emitted
Removing the final line (.for_each(|slice| println!("{:?}", slice))) prevents the ICE, implying that this is a codegen issue (as corroborated by the stack trace).
The following code triggers an ICE.
Code
Playground version
This example can no doubt be minimised further, but it should be obvious what I'm attempting to do and why. This would be, I assume, a fairly common use-case for GATs and are likely to be essential if GATs are ever to be integrated into
Iterator.Meta
rustc --version --verbose:Error output
Backtrace
Removing the final line (
.for_each(|slice| println!("{:?}", slice))) prevents the ICE, implying that this is a codegen issue (as corroborated by the stack trace).