Skip to content

typecheck_ice when attempting to type check trait object with duplicate associated types #81809

Description

@KenDJohnson

Code

Link to gist

use std::ops::Index;

pub trait Indexable {
    type Index;
}
struct Foo;
struct Bar;
impl Indexable for Foo { type Index = u8; }
impl Indexable for Bar { type Index = u16; }

pub trait Indexer<T: Indexable>: Index<T::Index, Output=T> {}

struct Store;

impl Index<u8> for Store {
    type Output = Foo;
    fn index(&self, _: u8) -> &Foo { panic!() }
}
impl Index<u16> for Store {
    type Output = Bar;
    fn index(&self, _: u16) -> &Bar { panic!() }
}
impl Indexer<Foo> for Store { }
impl Indexer<Bar> for Store { }

// implies StoreIndex: Index<u8, Output=Foo> + Index<u16, Output=Bar>
trait StoreIndex: Indexer<Foo> + Indexer<Bar> {}

impl StoreIndex for Store {}

struct Collection {
    stores: Vec<Store>,
}

trait StoreCollection {
    fn get_store(&self, _: usize) -> Option<&dyn StoreIndex>;
}

impl StoreCollection for Collection {
    //  Fails to compile:
    //    expected:
    //      Option<&dyn StoreIndex<Output = Bar, Output = Foo>
    //    found:
    //      Option<&Store>
    /*
    fn get_store(&self, i: usize) -> Option<&dyn StoreIndex> {
        self.stores.get(i)
    }
    */

    // ICE
    fn get_store(&self, i: usize) -> Option<&dyn StoreIndex> {
        if let Some(s) = self.stores.get(i) {
            Some(s as &dyn StoreIndex)
        } else {
            None
        }
    }

    // However, if the above is removed in favor of Indexing
    // type checking succeeds and the type of `&self.stores[i]`
    // is properly inferred
    /*
    fn get_store(&self, i: usize) -> Option<&dyn StoreIndex> {
        if i < self.stores.len() {
            Some(&self.stores[i])
        } else {
            None
        }
    }
    */
}

fn main() {}

Meta

rustc --version --verbose:

rustc 1.49.0 (e1884a8e3 2020-12-29)
binary: rustc
commit-hash: e1884a8e3c3e813aada8254edfa120e85bf5ffca
commit-date: 2020-12-29
host: x86_64-apple-darwin
release: 1.49.0

Error output

error: internal compiler error: broken MIR in DefId(0:33 ~ typecheck_ice[8acc]::{impl#7}::get_store) (CanonicalUserTypeAnnotation { user_ty: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Region(U0) }, CanonicalVarInfo { kind: Region(U0) }], value: Ty(&dyn StoreIndex<Output = Bar, Output = Foo>) }, span: src/main.rs:53:18: 53:38 (#0), inferred_ty: &dyn StoreIndex<Output = Bar, Output = Foo> }): bad user type (&dyn StoreIndex<Output = Bar, Output = Foo> = &dyn StoreIndex<Output = Bar, Output = Foo>): NoSolution
  |
  = note: delayed at compiler/rustc_mir/src/borrow_check/type_check/mod.rs:253:27

thread 'rustc' panicked at 'no errors encountered even though `delay_span_bug` issued', compiler/rustc_errors/src/lib.rs:974:13
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

error: internal compiler error: unexpected panic

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.49.0 (e1884a8e3 2020-12-29) running on x86_64-apple-darwin

note: compiler flags: -C embed-bitcode=no -C debuginfo=2 --crate-type bin

note: some of the compiler flags provided by cargo are hidden

query stack during panic:
end of query stack
error: could not compile `typecheck_ice`
Backtrace

thread 'rustc' panicked at 'no errors encountered even though `delay_span_bug` issued', compiler/rustc_errors/src/lib.rs:974:13
stack backtrace:
   0:        0x108a44934 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::ha0848bb2602b5d05
   1:        0x108aad0c0 - core::fmt::write::h9f3ccac2ef682b93
   2:        0x108a361f6 - std::io::Write::write_fmt::h0a47673aab280496
   3:        0x108a495b9 - std::panicking::default_hook::{{closure}}::h850c6aaf5e80c2f5
   4:        0x108a4927d - std::panicking::default_hook::h037801299da6e1c6
   5:        0x10bf29413 - rustc_driver::report_ice::h0fe9f8647d245792
   6:        0x108a49d9e - std::panicking::rust_panic_with_hook::h76436d4cf7a368ac
   7:        0x108a498a5 - std::panicking::begin_panic_handler::{{closure}}::h516c76d70abf04f6
   8:        0x108a44da8 - std::sys_common::backtrace::__rust_end_short_backtrace::h653290b4f930faed
   9:        0x108a4980a - _rust_begin_unwind
  10:        0x108ad0b0b - std::panicking::begin_panic_fmt::he778de6995efc6f5
  11:        0x1104eae96 - rustc_errors::HandlerInner::flush_delayed::hdb4fff43f77edaab
  12:        0x1104e700b - <rustc_errors::HandlerInner as core::ops::drop::Drop>::drop::hb7966f169f0d6c15
  13:        0x10bf1c26a - core::ptr::drop_in_place::hf30dd4a15888f71a
  14:        0x10bf1a666 - core::ptr::drop_in_place::hb8793afd37ab302e
  15:        0x10bf1e918 - <alloc::rc::Rc<T> as core::ops::drop::Drop>::drop::hb604ec874b74dec0
  16:        0x10bf339d2 - core::ptr::drop_in_place::hb2a870b8e6fe6c59
  17:        0x10bf2c272 - rustc_span::with_source_map::h687022d7ebb49e8d
  18:        0x10bf39ac1 - rustc_interface::interface::create_compiler_and_run::hea278ab322b44c40
  19:        0x10bf2c96f - rustc_span::with_session_globals::h7023df1cf3c9e104
  20:        0x10bf3e5b1 - std::sys_common::backtrace::__rust_begin_short_backtrace::hf0d8ecab3037d14f
  21:        0x10bebfa28 - core::ops::function::FnOnce::call_once{{vtable.shim}}::hd9d084f81e0dfcf8
  22:        0x108a581fd - std::sys::unix::thread::Thread::new::thread_start::hedb7cc0d930a8f40
  23:     0x7fff20482950 - __pthread_start

I did my best to create a small example for this, and I think this is a minimal instance of the problem. Looks like there is an error when trying to type check a cast to &dyn StoreIndex, for which the super traits expand to &dyn Index<u8, Output=Foo> + Index<u16, Output=Bar> which the typechecker seems to have issue by considering both constraints on Output regardless of the T indexing type (as StoreIndex<Output = Bar, Output = Foo> which it considers unsolvable since Bar != Foo.

The other two cases here are interesting as well. When get() is used directly, type checking fails but there is no ICE, but when the Vec<Store> is indexed directly &Store is automatically cast to &dyn StoreIndex and compilation succeeds.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: This is a bug.E-needs-testCall for participation: An issue has been fixed and does not reproduce, but no test has been added.I-ICEIssue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.glacierICE tracked in rust-lang/glacier.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions