Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
cushionbadak opened this issue Jun 4, 2024 · 3 comments
Assignees
Labels
C-bug Category: This is a bug. F-associated_const_equality `#![feature(associated_const_equality)]` F-generic_const_exprs `#![feature(generic_const_exprs)]` I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ requires-incomplete-features S-bug-has-test Status: This bug is tracked inside the repo by a `known-bug` test. S-has-mcve Status: A Minimal Complete and Verifiable Example has been found for this issue T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@cushionbadak
Copy link

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}")
    }
@cushionbadak cushionbadak added C-bug Category: This is a bug. I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jun 4, 2024
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Jun 4, 2024
@cushionbadak
Copy link
Author

@rustbot label +F-generic_const_exprs +F-associated_const_equality +requires-incomplete-features

@rustbot rustbot added F-associated_const_equality `#![feature(associated_const_equality)]` F-generic_const_exprs `#![feature(generic_const_exprs)]` requires-incomplete-features labels Jun 4, 2024
@jieyouxu jieyouxu added S-has-mcve Status: A Minimal Complete and Verifiable Example has been found for this issue and removed needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. labels Jun 4, 2024
@fmease fmease self-assigned this Jun 4, 2024
@fmease
Copy link
Member

fmease commented Jun 4, 2024

This has the very same underlying cause as #123456 and #123140.

@matthiaskrgr matthiaskrgr added the S-bug-has-test Status: This bug is tracked inside the repo by a `known-bug` test. label Jun 9, 2024
@cushionbadak
Copy link
Author

searched toolchains nightly-2022-01-01 through nightly-2024-05-30


********************************************************************************
Regression in nightly-2022-02-03
********************************************************************************

fetching https://static.rust-lang.org/dist/2022-02-02/channel-rust-nightly-git-commit-hash.txt
nightly manifest 2022-02-02: 40 B / 40 B [===================================================] 100.00 % 717.65 KB/s converted 2022-02-02 to 2681f253bcdb31a274411d2be456e7c6a1c67d62
fetching https://static.rust-lang.org/dist/2022-02-03/channel-rust-nightly-git-commit-hash.txt
nightly manifest 2022-02-03: 40 B / 40 B [===================================================] 100.00 % 610.55 KB/s converted 2022-02-03 to 27f5d830eb11cd7bdc834d6f0d78120976f75443
looking for regression commit between 2022-02-02 and 2022-02-03
fetching (via remote github) commits from max(2681f253bcdb31a274411d2be456e7c6a1c67d62, 2022-01-31) to 27f5d830eb11cd7bdc834d6f0d78120976f75443
ending github query because we found starting sha: 2681f253bcdb31a274411d2be456e7c6a1c67d62
get_commits_between returning commits, len: 7
  commit[0] 2022-02-01: Auto merge of #93442 - yaahc:Termination-abstraction, r=Mark-Simulacrum
  commit[1] 2022-02-01: Auto merge of #93285 - JulianKnodt:const_eq_2, r=oli-obk
  commit[2] 2022-02-02: Auto merge of #93466 - cjgillot:query-dead, r=nagisa
  commit[3] 2022-02-02: Auto merge of #93573 - matthiaskrgr:rollup-nrjmygz, r=matthiaskrgr
  commit[4] 2022-02-02: Auto merge of #93154 - michaelwoerister:fix-generic-closure-and-generator-debuginfo, r=wesleywiser
  commit[5] 2022-02-02: Auto merge of #93312 - pierwill:map-all-local-trait-impls, r=cjgillot
  commit[6] 2022-02-02: Auto merge of #93594 - matthiaskrgr:rollup-lcvhpdv, r=matthiaskrgr
ERROR: no CI builds available between 2681f253bcdb31a274411d2be456e7c6a1c67d62 and 27f5d830eb11cd7bdc834d6f0d78120976f75443 within last 167 days
cargo-bisect-rustc-bisect-rustc 0.6.8
cargo bisect-rustc --start=2022-01-01 --end=2024-05-30 --regress=ice --script=rustc --preserve -- 125957.rs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: This is a bug. F-associated_const_equality `#![feature(associated_const_equality)]` F-generic_const_exprs `#![feature(generic_const_exprs)]` I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ requires-incomplete-features S-bug-has-test Status: This bug is tracked inside the repo by a `known-bug` test. S-has-mcve Status: A Minimal Complete and Verifiable Example has been found for this issue T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

5 participants