From b130dd14aea5fa5fcf230ed4a147ac93f22868f4 Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Thu, 18 Jun 2026 23:55:07 +0900 Subject: [PATCH] `-Znext-solver` Emit error instead of ICE when combining {int, float} var with alias --- compiler/rustc_type_ir/src/relate/combine.rs | 26 +++++++++++++++++-- ...lize-assoc-ty-expected-int-var-no-ice-1.rs | 14 ++++++++++ ...y-expected-int-var-no-ice-2.current.stderr | 22 ++++++++++++++++ ...c-ty-expected-int-var-no-ice-2.next.stderr | 17 ++++++++++++ ...lize-assoc-ty-expected-int-var-no-ice-2.rs | 17 ++++++++++++ 5 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 tests/ui/traits/next-solver/normalize/normalize-assoc-ty-expected-int-var-no-ice-1.rs create mode 100644 tests/ui/traits/next-solver/normalize/normalize-assoc-ty-expected-int-var-no-ice-2.current.stderr create mode 100644 tests/ui/traits/next-solver/normalize/normalize-assoc-ty-expected-int-var-no-ice-2.next.stderr create mode 100644 tests/ui/traits/next-solver/normalize/normalize-assoc-ty-expected-int-var-no-ice-2.rs diff --git a/compiler/rustc_type_ir/src/relate/combine.rs b/compiler/rustc_type_ir/src/relate/combine.rs index 782e1fd7e37b4..37bbd6d920794 100644 --- a/compiler/rustc_type_ir/src/relate/combine.rs +++ b/compiler/rustc_type_ir/src/relate/combine.rs @@ -115,9 +115,31 @@ where panic!("We do not expect to encounter `Fresh` variables in the new solver") } - (_, ty::Alias(..)) | (ty::Alias(..), _) if infcx.next_trait_solver() => { + (other, ty::Alias(..)) | (ty::Alias(..), other) if infcx.next_trait_solver() => { match relation.structurally_relate_aliases() { - StructurallyRelateAliases::Yes => structurally_relate_tys(relation, a, b), + StructurallyRelateAliases::Yes => match other { + ty::Infer(infer_ty) => match infer_ty { + // Normally, we shouldn't be combining an infer ty with an alias here. But + // when we evaluate a `Projection(assoc_ty, expected)` goal, we normalize + // the projection term and structurally equate it with the expected term. If + // the normalized term is an alias type and the expected term is a ty var, + // the ty var just instantiated with the alias type without combining them. + // However, if the expected term is either an int var or a float var, e.g., + // when the expected term is an int literal that only can be fully inferred + // after the fallback, they are passed to this function because int/float + // vars can't be instantiated. As we can't structurally relate infer ty with + // another type, we just error them out here instead. + ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(_) => { + Err(TypeError::Sorts(ExpectedFound::new(a, b))) + } + + ty::InferTy::TyVar(_) + | ty::InferTy::FreshTy(_) + | ty::InferTy::FreshIntTy(_) + | ty::InferTy::FreshFloatTy(_) => unreachable!(), + }, + _ => structurally_relate_tys(relation, a, b), + }, StructurallyRelateAliases::No => { relation.register_alias_relate_predicate(a, b); Ok(a) diff --git a/tests/ui/traits/next-solver/normalize/normalize-assoc-ty-expected-int-var-no-ice-1.rs b/tests/ui/traits/next-solver/normalize/normalize-assoc-ty-expected-int-var-no-ice-1.rs new file mode 100644 index 0000000000000..3676007a83882 --- /dev/null +++ b/tests/ui/traits/next-solver/normalize/normalize-assoc-ty-expected-int-var-no-ice-1.rs @@ -0,0 +1,14 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@ check-pass + +// Regression test for + +trait Trait { + fn bar() -> impl Clone { + 1 + } +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/normalize/normalize-assoc-ty-expected-int-var-no-ice-2.current.stderr b/tests/ui/traits/next-solver/normalize/normalize-assoc-ty-expected-int-var-no-ice-2.current.stderr new file mode 100644 index 0000000000000..70d35e5cbc5b2 --- /dev/null +++ b/tests/ui/traits/next-solver/normalize/normalize-assoc-ty-expected-int-var-no-ice-2.current.stderr @@ -0,0 +1,22 @@ +error[E0271]: expected `foo` to return `{integer}`, but it returns `impl Sized` + --> $DIR/normalize-assoc-ty-expected-int-var-no-ice-2.rs:13:10 + | +LL | fn foo() -> impl Sized {} + | ---------- the found opaque type +... +LL | proj(x, 1); + | ---- ^ expected integer, found opaque type + | | + | required by a bound introduced by this call + | + = note: expected type `{integer}` + found opaque type `impl Sized` +note: required by a bound in `proj` + --> $DIR/normalize-assoc-ty-expected-int-var-no-ice-2.rs:9:24 + | +LL | fn proj U, U>(x: Option, y: U) {} + | ^ required by this bound in `proj` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/next-solver/normalize/normalize-assoc-ty-expected-int-var-no-ice-2.next.stderr b/tests/ui/traits/next-solver/normalize/normalize-assoc-ty-expected-int-var-no-ice-2.next.stderr new file mode 100644 index 0000000000000..f5d50e6d29ed4 --- /dev/null +++ b/tests/ui/traits/next-solver/normalize/normalize-assoc-ty-expected-int-var-no-ice-2.next.stderr @@ -0,0 +1,17 @@ +error[E0271]: type mismatch resolving ` impl Sized {foo} as FnOnce<()>>::Output == {integer}` + --> $DIR/normalize-assoc-ty-expected-int-var-no-ice-2.rs:13:10 + | +LL | proj(x, 1); + | ---- ^ types differ + | | + | required by a bound introduced by this call + | +note: required by a bound in `proj` + --> $DIR/normalize-assoc-ty-expected-int-var-no-ice-2.rs:9:24 + | +LL | fn proj U, U>(x: Option, y: U) {} + | ^ required by this bound in `proj` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/next-solver/normalize/normalize-assoc-ty-expected-int-var-no-ice-2.rs b/tests/ui/traits/next-solver/normalize/normalize-assoc-ty-expected-int-var-no-ice-2.rs new file mode 100644 index 0000000000000..ca7870459b5c4 --- /dev/null +++ b/tests/ui/traits/next-solver/normalize/normalize-assoc-ty-expected-int-var-no-ice-2.rs @@ -0,0 +1,17 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +// Regression test for + +fn foo() -> impl Sized {} + +fn proj U, U>(x: Option, y: U) {} + +fn main() { + let mut x = None; + proj(x, 1); + //[current]~^ ERROR: expected `foo` to return `{integer}`, but it returns `impl Sized` + //[next]~^^ ERROR: type mismatch resolving ` impl Sized {foo} as FnOnce<()>>::Output == {integer}` + x = Some(foo); +}