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: Encountered unexpected type in ConstructorSet::for_ty in rustc_pattern_analysis/src/rustc.rs #125874

Closed
cushionbadak opened this issue Jun 2, 2024 · 1 comment · Fixed by #135057
Labels
A-patterns Relating to patterns and pattern matching C-bug Category: This is a bug. I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ 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

cushionbadak commented Jun 2, 2024

Code

(hand reduced)

pub trait A {}

pub trait Mirror {
    type Assoc: ?Sized;
}
impl<T: ?Sized> Mirror for dyn A {
    type Assoc = T;
}

struct Bar {
    foo: <dyn A + 'static as Mirror>::Assoc,
}

pub fn main() {
    let strct = Bar { foo: 3 };

    match strct {
        Bar { foo: 1, .. } => {}
        _ => (),
    };
}
  • Compared to original code, keyword dyn added at impl<T: ?Sized> Mirror for dyn A, to reduce error message.
original code

pub trait A {}
pub trait B: A {}

pub trait Mirror {
    type Assoc: ?Sized;
}
impl<T: ?Sized> Mirror for A {
    type Assoc = T;
}

pub fn foo<'a>(x: &'a <dyn A + 'static as Mirror>::Assoc) -> &'a <dyn B + 'static as Mirror>::Assoc {
    static
}


//@ run-pass

#![feature(postfix_match)]

struct Bar {
    foo: <dyn A + 'static as Mirror>::Assoc,
    baz: u8,
}

pub fn main() {
    let thing = Some("thing");

    thing.match {
        Some("nothing") => {},
        Some(text) if text.eq_ignore_ascii_case("tapir")  => {},
        Some("true") | Some("false") => {},
        Some("thing") => {},
        Some(_) => {},
        None => {}
    };

    let num = 2u8;

    num.match {
        0 => {},
        1..=5 => {},
        _ => {},
    };

    let slic = &[1, 2, 3, 4][..];

    slic.match {
        [1] => {},
        [2, _tail @ ..] => {},
        [1, _] => {},
        _ => {},
    };

    slic[0].match {
        1 => 0,
        i => i,
    };

    let out = (1, 2).match {
        (1, 3) => 0,
        (_, 1) => 0,
        (1, i) => i,
        _ => 3,
    };
    assert!(out == 2);

    let strct = Bar {
        foo: 3,
        baz: 4
    };

    strct.match {
        Bar { foo: 1, .. } => {},
        Bar { baz: 2, .. } => {},
        _ => (),
    };
}

Meta

rustc --version --verbose:

rustc 1.80.0-nightly (f67a1acc0 2024-06-01)
binary: rustc
commit-hash: f67a1acc04c7ecbf05751b17592dd8d245b75256
commit-date: 2024-06-01
host: aarch64-apple-darwin
release: 1.80.0-nightly
LLVM version: 18.1.6

Error output

Command: rustc

error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
 --> r_rustc_1A93F6.rs:6:6
  |
6 | impl<T: ?Sized> Mirror for dyn A {
  |      ^ unconstrained type parameter

error[E0282]: type annotations needed
  --> r_rustc_1A93F6.rs:11:10
   |
11 |     foo: <dyn A + 'static as Mirror>::Assoc,
   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T`
Backtrace

error: internal compiler error: compiler/rustc_pattern_analysis/src/rustc.rs:412:17: Encountered unexpected type in `ConstructorSet::for_ty`: ?0t

thread 'rustc' panicked at compiler/rustc_pattern_analysis/src/rustc.rs:412: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_pattern_analysis::rustc::RustcPatCtxt>::ctors_for_ty
   7: rustc_pattern_analysis::usefulness::compute_exhaustiveness_and_usefulness::<rustc_pattern_analysis::rustc::RustcPatCtxt>
   8: rustc_pattern_analysis::usefulness::compute_exhaustiveness_and_usefulness::<rustc_pattern_analysis::rustc::RustcPatCtxt>
   9: rustc_pattern_analysis::usefulness::compute_match_usefulness::<rustc_pattern_analysis::rustc::RustcPatCtxt>
  10: rustc_pattern_analysis::analyze_match
  11: <rustc_mir_build::thir::pattern::check_match::MatchVisitor>::analyze_patterns
  12: <rustc_mir_build::thir::pattern::check_match::MatchVisitor>::check_match
  13: <rustc_mir_build::thir::pattern::check_match::MatchVisitor as rustc_middle::thir::visit::Visitor>::visit_expr
  14: <rustc_mir_build::thir::pattern::check_match::MatchVisitor as rustc_middle::thir::visit::Visitor>::visit_expr
  15: rustc_middle::thir::visit::walk_expr::<rustc_mir_build::thir::pattern::check_match::MatchVisitor>
  16: <rustc_mir_build::thir::pattern::check_match::MatchVisitor as rustc_middle::thir::visit::Visitor>::visit_expr
  17: <rustc_mir_build::thir::pattern::check_match::MatchVisitor as rustc_middle::thir::visit::Visitor>::visit_expr
  18: rustc_mir_build::thir::pattern::check_match::check_match
      [... omitted 2 frames ...]
  19: rustc_mir_build::build::mir_build
  20: rustc_mir_transform::mir_built
      [... omitted 2 frames ...]
  21: rustc_mir_build::check_unsafety::check_unsafety
      [... omitted 2 frames ...]
  22: <rustc_middle::hir::map::Map>::par_body_owners::<rustc_interface::passes::run_required_analyses::{closure#1}::{closure#0}>::{closure#0}
  23: <rustc_data_structures::sync::parallel::ParallelGuard>::run::<(), rustc_data_structures::sync::parallel::enabled::par_for_each_in<&rustc_span::def_id::LocalDefId, &[rustc_span::def_id::LocalDefId], <rustc_middle::hir::map::Map>::par_body_owners<rustc_interface::passes::run_required_analyses::{closure#1}::{closure#0}>::{closure#0}>::{closure#0}::{closure#0}::{closure#0}>
  24: <rustc_session::session::Session>::time::<(), rustc_interface::passes::run_required_analyses::{closure#1}>
  25: rustc_interface::passes::analysis
      [... omitted 2 frames ...]
  26: <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}>
  27: <rustc_interface::interface::Compiler>::enter::<rustc_driver_impl::run_compiler::{closure#0}::{closure#1}, core::result::Result<core::option::Option<rustc_interface::queries::Linker>, rustc_span::ErrorGuaranteed>>
  28: <scoped_tls::ScopedKey<rustc_span::SessionGlobals>>::set::<rustc_interface::util::run_in_thread_with_globals<rustc_interface::util::run_in_thread_pool_with_globals<rustc_interface::interface::run_compiler<core::result::Result<(), rustc_span::ErrorGuaranteed>, rustc_driver_impl::run_compiler::{closure#0}>::{closure#1}, core::result::Result<(), rustc_span::ErrorGuaranteed>>::{closure#0}, core::result::Result<(), rustc_span::ErrorGuaranteed>>::{closure#0}::{closure#0}::{closure#0}, core::result::Result<(), rustc_span::ErrorGuaranteed>>
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 `/Users/jisukbyun/workspace/240531_100chaos_tree_combine_typ/icefiles/rustc-ice-2024-06-02T02_04_15-52985.txt` to your bug report

query stack during panic:
#0 [check_match] match-checking `main`
#1 [mir_built] building MIR for `main`
#2 [check_unsafety] unsafety-checking `main`
#3 [analysis] running analysis passes on this crate
end of query stack
error: aborting due to 3 previous errors

Some errors have detailed explanations: E0207, E0282.
For more information about an error, try `rustc --explain E0207`.

Note

  • ICE location: rustc_pattern_analysis/src/rustc.rs L412
    ty::CoroutineWitness(_, _) | ty::Bound(_, _) | ty::Placeholder(_) | ty::Infer(_) => {
    bug!("Encountered unexpected type in `ConstructorSet::for_ty`: {ty:?}")
    }
@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 2, 2024
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Jun 2, 2024
@jieyouxu jieyouxu added A-patterns Relating to patterns and pattern matching 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
@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 nightlies: from nightly-2023-01-01 to nightly-2024-05-30
regressed nightly: nightly-2024-03-08
searched commit range: 7d3702e...9c3ad80
regressed commit: 8c9a75b

bisected with cargo-bisect-rustc v0.6.8

Host triple: x86_64-unknown-linux-gnu
Reproduce with:

cargo bisect-rustc --start=2023-01-01 --end=2024-05-30 --regress=ice --script=rustc --preserve -- 125874.rs

bors added a commit to rust-lang-ci/rust that referenced this issue Jan 3, 2025
…d, r=<try>

Project to `TyKind::Error` when there are unconstrained non-lifetime (ty/const) impl params

I think this is a bit less invasive of an approach compared to rust-lang#127973.

It splits the `enforce_impl_params_are_constrained` function into lifetime/non-lifetime, and queryfies the latter. We can then use the result of the latter query (`Result<(), ErrorGuaranteed>`) to intercept projection and constrain the projected type to `TyKind::Error`, which ensures that we leak no ty or const vars to places that don't expect them, like `normalize_erasing_regions`.

The reason we split `enforce_impl_params_are_constrained` into two parts is because we only error for *lifetimes* if the lifetime ends up showing up in any of the associated types of the impl (e.g. we allow `impl<'a> Foo { type Assoc = (); }`). However, in order to compute the `type_of` query for the anonymous associated type of an RPITIT, we need to do trait solving (in `query collect_return_position_impl_trait_in_trait_tys`). That would induce cycles. Luckily, it turns out for lifetimes we don't even care about if they're unconstrained, since they're erased in all contexts that we are trying to fix ICEs. So it's sufficient to keep this check separated out of the query.

Fixes rust-lang#123141
Fixes rust-lang#125874
Fixes rust-lang#126942
Fixes rust-lang#127804
Fixes rust-lang#130967

r? oli-obk
bors added a commit to rust-lang-ci/rust that referenced this issue Jan 3, 2025
…d, r=<try>

Project to `TyKind::Error` when there are unconstrained non-lifetime (ty/const) impl params

It splits the `enforce_impl_params_are_constrained` function into lifetime/non-lifetime, and queryfies the latter. We can then use the result of the latter query (`Result<(), ErrorGuaranteed>`) to intercept projection and constrain the projected type to `TyKind::Error`, which ensures that we leak no ty or const vars to places that don't expect them, like `normalize_erasing_regions`.

The reason we split `enforce_impl_params_are_constrained` into two parts is because we only error for *lifetimes* if the lifetime ends up showing up in any of the associated types of the impl (e.g. we allow `impl<'a> Foo { type Assoc = (); }`). However, in order to compute the `type_of` query for the anonymous associated type of an RPITIT, we need to do trait solving (in `query collect_return_position_impl_trait_in_trait_tys`). That would induce cycles. Luckily, it turns out for lifetimes we don't even care about if they're unconstrained, since they're erased in all contexts that we are trying to fix ICEs. So it's sufficient to keep this check separated out of the query.

I think this is a bit less invasive of an approach compared to rust-lang#127973. The major difference between this PR and that PR is that we queryify the check instead of merging it into the `explicit_predicates_of` query, and we use the result to taint just projection goals, rather than trait goals too. This doesn't require a lot of new tracking in `ItemCtxt` and `GenericPredicates`, and it also seems to not require any other changes to typeck like that PR did.

Fixes rust-lang#123141
Fixes rust-lang#125874
Fixes rust-lang#126942
Fixes rust-lang#127804
Fixes rust-lang#130967

r? oli-obk
bors added a commit to rust-lang-ci/rust that referenced this issue Jan 3, 2025
…d, r=oli-obk

Project to `TyKind::Error` when there are unconstrained non-lifetime (ty/const) impl params

It splits the `enforce_impl_params_are_constrained` function into lifetime/non-lifetime, and queryfies the latter. We can then use the result of the latter query (`Result<(), ErrorGuaranteed>`) to intercept projection and constrain the projected type to `TyKind::Error`, which ensures that we leak no ty or const vars to places that don't expect them, like `normalize_erasing_regions`.

The reason we split `enforce_impl_params_are_constrained` into two parts is because we only error for *lifetimes* if the lifetime ends up showing up in any of the associated types of the impl (e.g. we allow `impl<'a> Foo { type Assoc = (); }`). However, in order to compute the `type_of` query for the anonymous associated type of an RPITIT, we need to do trait solving (in `query collect_return_position_impl_trait_in_trait_tys`). That would induce cycles. Luckily, it turns out for lifetimes we don't even care about if they're unconstrained, since they're erased in all contexts that we are trying to fix ICEs. So it's sufficient to keep this check separated out of the query.

I think this is a bit less invasive of an approach compared to rust-lang#127973. The major difference between this PR and that PR is that we queryify the check instead of merging it into the `explicit_predicates_of` query, and we use the result to taint just projection goals, rather than trait goals too. This doesn't require a lot of new tracking in `ItemCtxt` and `GenericPredicates`, and it also seems to not require any other changes to typeck like that PR did.

Fixes rust-lang#123141
Fixes rust-lang#125874
Fixes rust-lang#126942
Fixes rust-lang#127804
Fixes rust-lang#130967

r? oli-obk
@bors bors closed this as completed in 7349f6b Jan 4, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-patterns Relating to patterns and pattern matching C-bug Category: This is a bug. I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ 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
4 participants