Skip to content

ICE: unexpected type encountered in variance inference in rustc_hir_analysis/src/variance/constraints.rs #125957

@cushionbadak

Description

@cushionbadak

Code

(hand-reduced & simplified)

#![feature(generic_const_exprs)] #![allow(incomplete_features)] #![feature(associated_const_equality)] pub struct Equal<const T: usize, const R: usize>(); pub enum ParseMode { Raw, } pub trait Parse { const PARSE_MODE: ParseMode; } pub trait RenderRaw: Parse<PARSE_MODE = { ParseMode::Raw }> {} trait GenericVec<T> { fn unwrap() -> dyn RenderRaw; } fn main() {}
(original, 300+ lines)

//@ check-pass #![feature(generic_const_exprs)] #![allow(incomplete_features)] use std::marker::PhantomData; pub struct Equal<const T: usize, const R: usize>(); pub trait True {} impl<const T: usize> True for Equal<T, T> {} // replacement for generativity pub struct Id<'id>(PhantomData<fn(&'id ()) -> &'id ()>); pub struct Guard<'id>(Id<'id>); fn make_guard<'id>(i: &'id Id<'id>) -> Guard<'id> { Guard(Id(PhantomData)) } impl<'id> Into<Id<'id>> for Guard<'id> { fn into(self) -> Id<'id> { self.0 } } pub struct Arena<'life> { bytes: *mut [u8], //bitmap: RefCell<RoaringBitmap>, _token: PhantomData<Id<'life>>, } #[repr(transparent)] pub struct Item<'life, T> { data: T, _phantom: PhantomData<Id<'life>>, } #[repr(transparent)] pub struct Token<'life, 'borrow, 'compact, 'reborrow, T> where 'life: 'reborrow, T: Tokenize<'life, 'borrow, 'compact, 'reborrow>, { //ptr: *mut <T as Tokenize>::Tokenized, ptr: core::ptr::NonNull<T::Tokenized>, _phantom: PhantomData<Id<'life>>, _compact: PhantomData<&'borrow Guard<'compact>>, _result: PhantomData<&'reborrow T::Untokenized>, } impl<'life> Arena<'life> { pub fn tokenize<'before, 'compact, 'borrow, 'reborrow, T, U>( &self, guard: &'borrow Guard<'compact>, item: Item<'life, &'before mut T>, ) -> Token<'life, 'borrow, 'compact, 'reborrow, U> where T: Tokenize<'life, 'borrow, 'compact, 'reborrow, Untokenized = U>, T::Untokenized: Tokenize<'life, 'borrow, 'compact, 'reborrow>, Equal<{ core::mem::size_of::<T>() }, { core::mem::size_of::<U>() }>: True, 'compact: 'borrow, 'life: 'reborrow, 'life: 'compact, 'life: 'borrow, // 'borrow: 'before ?? { let dst = item.data as *mut T as *mut T::Tokenized; Token { ptr: core::ptr::NonNull::new(dst as *mut _).unwrap(), _phantom: PhantomData, _compact: PhantomData, _result: PhantomData, } } } pub trait Tokenize<'life, 'borrow, 'compact, 'reborrow> where 'compact: 'borrow, 'life: 'reborrow, 'life: 'borrow, 'life: 'compact, { type Tokenized; type Untokenized; const TO: fn(&Arena<'life>, &'borrow Guard<'compact>, Self) -> Self::Tokenized; const FROM: fn(&'reborrow Arena<'life>, Self::Tokenized) -> Self::Untokenized; } macro_rules! tokenize { ($to:expr, $from:expr) => { const TO: fn(&Arena<'life>, &'borrow Guard<'compact>, Self) -> Self::Tokenized = $to; const FROM: fn(&'reborrow Arena<'life>, Self::Tokenized) -> Self::Untokenized = $from; }; } struct Foo<'life, 'borrow>(Option<Item<'life, &'borrow mut Bar>>); struct TokenFoo<'life, 'borrow, 'compact, 'reborrow>( Option<Token<'life, 'borrow, 'compact, 'reborrow, Bar>>, ); struct Bar(u8); impl<'life, 'before, 'borrow, 'compact, 'reborrow> Tokenize<'life, 'borrow, 'compact, 'reborrow> for Foo<'life, 'before> where 'compact: 'borrow, 'life: 'reborrow, 'life: 'borrow, 'life: 'compact, { type Tokenized = TokenFoo<'life, 'borrow, 'compact, 'reborrow>; type Untokenized = Foo<'life, 'reborrow>; tokenize!(foo_to, foo_from); } impl<'life, 'borrow, 'compact, 'reborrow> Tokenize<'life, 'borrow, 'compact, 'reborrow> for Bar where 'compact: 'borrow, 'life: 'reborrow, 'life: 'borrow, 'life: 'compact, { type Tokenized = Bar; type Untokenized = Bar; tokenize!(bar_to, bar_from); } fn bar_to<'life, 'borrow, 'compact>( arena: &Arena<'life>, guard: &'borrow Guard<'compact>, s: Bar, ) -> Bar { s } fn bar_from<'life, 'reborrow>(arena: &'reborrow Arena<'life>, s: Bar) -> Bar { s } fn foo_to<'life, 'borrow, 'compact, 'reborrow, 'before>( arena: &'before Arena<'life>, guard: &'borrow Guard<'compact>, s: Foo<'life, 'before>, ) -> TokenFoo<'life, 'borrow, 'compact, 'reborrow> { let Foo(bar) = s; TokenFoo(bar.map(|bar| arena.tokenize(guard, bar))) } fn foo_from<'life, 'borrow, 'compact, 'reborrow>( arena: &'reborrow Arena<'life>, s: TokenFoo<'life, 'borrow, 'compact, 'reborrow>, ) -> Foo<'life, 'reborrow> { Foo(s.0.map(|bar| panic!())) } fn main() {} #![feature(generic_associated_types)] trait Fun { type F<'a>: Fn() -> u32; fn callme<'a>(f: Self::F<'a>) -> u32 { f() } } impl <T> Fun for T { type F<'a> = Self; } fn main() { <u8>::callme(0); } #![allow(incomplete_features)] #![feature(adt_const_params, const_ptr_read, generic_const_exprs)] use std::mem::ManuallyDrop; const fn concat_strs<const A: &'static str, const B: &'static str>() -> &'static str where [(); A.len()]:, [(); B.len()]:, [(); A.len() + B.len()]:, { #[repr(C)] struct ConcatJoin<const N: usize, const M: usize> { left: [u8; N], right: [u8; M], } #[repr(C)] union ConcatJoinerItem where [(); N + M]:, { whole: ManuallyDrop<[u8; N + M]>, split: ManuallyDrop<ConcatJoin<N, M>>, } const fn concat_arr<const M: usize, const N: usize>(a: [u8; M], b: [u8; N]) -> [u8; M + N] where [(); M + N]:, { unsafe { let joiner = ConcatJoiner { split: ManuallyDrop::new(ConcatJoin { left: a, right: b }), }; let join = joiner.whole; ManuallyDrop::into_inner(join) } } struct Inner<const A: &'static str, const B: &'static str>; impl<const A: &'static str, const B: &'static str> Inner<A, B> where [(); A.len()]:, [(); B.len()]:, [(); A.len() + B.len()]:, { const ABSTR: &'static str = unsafe { std::str::from_utf8_unchecked(&concat_arr( A.as_ptr().cast::<[u8; A.len()]>().read(), B.as_ptr().cast::<[u8; B.len()]>().read(), )) }; } Inner::<A, B>::ABSTR } const FOO: &str = "foo"; const BAR: &str = "bar"; const FOOBAR: &str = concat_strs::<FOO, BAR>(); pub fn main() {} //@ aux-build:issue-20727.rs //@ ignore-cross-compile // https://github.com/rust-lang/rust/issues/20727 #![crate_name="issue_20727_3"] extern crate issue_20727; pub trait Bar {} // @has issue_20727_3/trait.Deref2.html pub trait Deref2 { // @has - '//pre[@class="rust item-decl"]' 'trait Deref2 {' // @has - '//pre[@class="rust item-decl"]' 'type Target: Bar;' type Target: Bar; // @has - '//pre[@class="rust item-decl"]' 'fn deref(&self) -> Self::Target;' fn deref(&self) -> Self::Target; } // @has issue_20727_3/reexport/trait.Deref2.html pub mod reexport { // @has - '//pre[@class="rust item-decl"]' 'trait Deref2 {' // @has - '//pre[@class="rust item-decl"]' 'type Target: Bar;' // @has - '//pre[@class="rust item-decl"]' 'fn deref(&self) -> Self::Target;' pub use issue_20727::Deref2; } #![feature(associated_const_equality)] pub enum ParseMode { Raw, } pub trait Parse { const PARSE_MODE: Self::F; } pub trait RenderRaw: Parse<PARSE_MODE = { ParseMode::Raw }> {} // Regression test for #53570. Here, we need to propagate that `T: 'a` // but in some versions of NLL we were propagating a stronger // requirement that `T: 'static`. This arose because we actually had // to propagate both that `T: 'a` but also `T: 'b` where `'b` is the // higher-ranked lifetime that appears in the type of the closure // parameter `x` -- since `'b` cannot be expressed in the caller's // space, that got promoted th `'static`. // //@ check-pass use std::cell::{RefCell, Ref}; trait AnyVec { } trait GenericVec<T> { fn unwrap<'a, 'b>(vec: &'b dyn AnyVec<'a>) -> &'b [RenderRaw] where T: 'a; } struct Scratchpad<'a> { buffers: RefCell<Box<dyn AnyVec<'a>>>, } impl<'a> Scratchpad<'a> { fn get<Deref2>(&self) -> Ref<[T]> where T: 'a { Ref::map(self.buffers.borrow(), |x| T::unwrap(x.as_ref())) } } fn main() { }

Meta

rustc --version --verbose:

rustc 1.80.0-nightly (7c52d2db6 2024-06-03) binary: rustc commit-hash: 7c52d2db6348b038276198e88a835125849f322e commit-date: 2024-06-03 host: x86_64-apple-darwin release: 1.80.0-nightly LLVM version: 18.1.6 

Error output

Command: rustc

<output> 
Backtrace

error: internal compiler error: compiler/rustc_hir_analysis/src/variance/constraints.rs:331:17: unexpected type encountered in variance inference: FreshTy(0) thread 'rustc' panicked at compiler/rustc_hir_analysis/src/variance/constraints.rs:331:17: Box<dyn Any> stack backtrace: 0: std::panicking::begin_panic::<rustc_errors::ExplicitBug> 1: <rustc_errors::diagnostic::BugAbort as rustc_errors::diagnostic::EmissionGuarantee>::emit_producing_guarantee 2: rustc_middle::util::bug::opt_span_bug_fmt::<rustc_span::span_encoding::Span>::{closure#0} 3: rustc_middle::ty::context::tls::with_opt::<rustc_middle::util::bug::opt_span_bug_fmt<rustc_span::span_encoding::Span>::{closure#0}, !>::{closure#0} 4: rustc_middle::ty::context::tls::with_context_opt::<rustc_middle::ty::context::tls::with_opt<rustc_middle::util::bug::opt_span_bug_fmt<rustc_span::span_encoding::Span>::{closure#0}, !>::{closure#0}, !> 5: rustc_middle::util::bug::bug_fmt 6: <rustc_hir_analysis::variance::constraints::ConstraintContext>::add_constraints_from_ty 7: <rustc_hir_analysis::variance::constraints::ConstraintContext>::add_constraints_from_invariant_args 8: <rustc_hir_analysis::variance::constraints::ConstraintContext>::add_constraints_from_ty 9: <rustc_hir_analysis::variance::constraints::ConstraintContext>::build_constraints_for_item 10: rustc_hir_analysis::variance::crate_variances [... omitted 1 frame ...] 11: rustc_hir_analysis::variance::variances_of [... omitted 2 frames ...] 12: rustc_middle::query::plumbing::query_get_at::<rustc_query_system::query::caches::DefIdCache<rustc_middle::query::erase::Erased<[u8; 16]>>> 13: rustc_hir_analysis::check::wfcheck::check_variances_for_type_defn 14: rustc_hir_analysis::check::wfcheck::check_well_formed [... omitted 1 frame ...] 15: rustc_middle::query::plumbing::query_ensure_error_guaranteed::<rustc_query_system::query::caches::VecCache<rustc_hir::hir_id::OwnerId, rustc_middle::query::erase::Erased<[u8; 1]>>, ()> 16: rustc_hir_analysis::check::wfcheck::check_mod_type_wf [... omitted 1 frame ...] 17: rustc_hir_analysis::check_crate 18: rustc_interface::passes::run_required_analyses 19: rustc_interface::passes::analysis [... omitted 1 frame ...] 20: <rustc_interface::queries::QueryResult<&rustc_middle::ty::context::GlobalCtxt>>::enter::<core::result::Result<(), rustc_span::ErrorGuaranteed>, rustc_driver_impl::run_compiler::{closure#0}::{closure#1}::{closure#3}> 21: rustc_interface::interface::run_compiler::<core::result::Result<(), rustc_span::ErrorGuaranteed>, rustc_driver_impl::run_compiler::{closure#0}>::{closure#1} note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace. 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: please make sure that you have updated to the latest nightly note: please attach the file at `/Volumes/T7/workspace/240604_combine_gb/icefiles/rustc-ice-2024-06-04T05_59_01-56677.txt` to your bug report query stack during panic: #0 [crate_variances] computing the variances for items in this crate #1 [variances_of] computing the variances of `Equal` #2 [check_well_formed] checking that `Equal` is well-formed #3 [check_mod_type_wf] checking that types are well-formed in top-level module #4 [analysis] running analysis passes on this crate end of query stack error: aborting due to 1 previous error 

Note

  • ICE location: rustc_hir_analysis/src/variance/constraints.rs L331
    ty::Placeholder(..) | ty::CoroutineWitness(..) | ty::Bound(..) | ty::Infer(..) => {
    bug!("unexpected type encountered in variance inference: {}", ty);
    }
    • Fixed ICE issue-109071 has identical ICE location
  • If the struct definition pub struct Equal<const T: usize, const R: usize>(); is erased, an ICE will occur at compiler/rustc_infer/src/infer/relate/generalize.rs L456. My guess is that this has already been reported in issue ICE: unexpected infer type #123140.
    let g = match *t.kind() {
    ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
    bug!("unexpected infer type: {t}")
    }

Metadata

Metadata

Assignees

Labels

C-bugCategory: This is a bug.F-associated_const_equality`#![feature(associated_const_equality)]`F-generic_const_exprs`#![feature(generic_const_exprs)]`I-ICEIssue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️S-bug-has-testStatus: This bug is tracked inside the repo by a `known-bug` test.S-has-mcveStatus: A Minimal Complete and Verifiable Example has been found for this issueT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

Type

No type

Projects

Status

Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions