diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index 4d712e9ffd372..f9c7e43fc4125 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -456,17 +456,32 @@ impl<'cx, 'tcx> TypeFolder> for Canonicalizer<'cx, 'tcx> { fn fold_const(&mut self, mut ct: ty::Const<'tcx>) -> ty::Const<'tcx> { match ct.kind() { ty::ConstKind::Infer(InferConst::Var(mut vid)) => { + let Some(infcx) = self.infcx else { + // FIXME(with_negative_coherence): the infcx has constraints from equating + // the impl headers in `impl_intersection_has_negative_obligation`. + // We should use these constraints as assumptions. + assert!(self.tcx.features().with_negative_coherence); + debug!("canonicalizing `ConstKind::Infer` without an `infcx`?"); + assert!(!self.canonicalize_mode.preserve_universes()); + return self.canonicalize_const_var( + CanonicalVarInfo { + kind: CanonicalVarKind::Const(ty::UniverseIndex::ROOT, ct.ty()), + }, + ct, + ); + }; + // We need to canonicalize the *root* of our const var. // This is so that our canonical response correctly reflects // any equated inference vars correctly! - let root_vid = self.infcx.unwrap().root_const_var(vid); + let root_vid = infcx.root_const_var(vid); if root_vid != vid { ct = ty::Const::new_var(self.tcx, root_vid, ct.ty()); vid = root_vid; } debug!("canonical: const var found with vid {:?}", vid); - match self.infcx.unwrap().probe_const_var(vid) { + match infcx.probe_const_var(vid) { Ok(c) => { debug!("(resolved to {:?})", c); return self.fold_const(c); @@ -487,7 +502,19 @@ impl<'cx, 'tcx> TypeFolder> for Canonicalizer<'cx, 'tcx> { } } ty::ConstKind::Infer(InferConst::EffectVar(vid)) => { - match self.infcx.unwrap().probe_effect_var(vid) { + let Some(infcx) = self.infcx else { + // FIXME(with_negative_coherence): the infcx has constraints from equating + // the impl headers in `impl_intersection_has_negative_obligation`. + // We should use these constraints as assumptions. + assert!(self.tcx.features().with_negative_coherence); + debug!("canonicalizing `ConstKind::Infer` without an `infcx`?"); + return self.canonicalize_const_var( + CanonicalVarInfo { kind: CanonicalVarKind::Effect }, + ct, + ); + }; + + match infcx.probe_effect_var(vid) { Some(value) => return self.fold_const(value), None => { return self.canonicalize_const_var( diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs index 93f9c2333f0c0..c84290b19f890 100644 --- a/compiler/rustc_trait_selection/src/traits/misc.rs +++ b/compiler/rustc_trait_selection/src/traits/misc.rs @@ -215,8 +215,12 @@ pub fn check_tys_might_be_eq<'tcx>( let (infcx, key, _) = tcx.infer_ctxt().build_with_canonical(DUMMY_SP, &canonical); let (param_env, (ty_a, ty_b)) = key.into_parts(); let ocx = ObligationCtxt::new(&infcx); + let cause = ObligationCause::dummy(); + + let ty_a = ocx.deeply_normalize(&cause, param_env, ty_a).unwrap_or(ty_a); + let ty_b = ocx.deeply_normalize(&cause, param_env, ty_b).unwrap_or(ty_b); + let result = ocx.eq(&cause, param_env, ty_a, ty_b); - let result = ocx.eq(&ObligationCause::dummy(), param_env, ty_a, ty_b); // use `select_where_possible` instead of `select_all_or_error` so that // we don't get errors from obligations being ambiguous. let errors = ocx.select_where_possible(); diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 0a861d62c3726..93bf52597e7c5 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -381,7 +381,7 @@ impl<'test> TestCx<'test> { // if a test does not crash, consider it an error if proc_res.status.success() || matches!(proc_res.status.code(), Some(1 | 0)) { self.fatal(&format!( - "test no longer crashes/triggers ICE! Please give it a mearningful name, \ + "test no longer crashes/triggers ICE! Please give it a meaningful name, \ add a doc-comment to the start of the test explaining why it exists and \ move it to tests/ui or wherever you see fit." )); diff --git a/tests/crashes/114456-2.rs b/tests/crashes/114456-2.rs deleted file mode 100644 index eca27febb968a..0000000000000 --- a/tests/crashes/114456-2.rs +++ /dev/null @@ -1,20 +0,0 @@ -//@ known-bug: #114456 -#![feature(adt_const_params)] - -const EMPTY_MATRIX: ::Matrix = [0; 1]; - -pub struct Walk::Matrix> {} - -impl Walk { - pub const fn new() -> Self { - Self {} - } -} - -pub enum Type {} -pub trait Trait { type Matrix; } -impl Trait for Type { type Matrix = [usize; 1]; } - -fn main() { - let _ = Walk::new(); -} diff --git a/tests/crashes/114456.rs b/tests/crashes/114456.rs deleted file mode 100644 index e347327e73863..0000000000000 --- a/tests/crashes/114456.rs +++ /dev/null @@ -1,17 +0,0 @@ -//@ known-bug: #114456 -#![feature(adt_const_params, lazy_type_alias)] - -pub type Matrix = [usize; 1]; -const EMPTY_MATRIX: Matrix = [0; 1]; - -pub struct Walk {} - -impl Walk { - pub const fn new() -> Self { - Self {} - } -} - -fn main() { - let _ = Walk::new(); -} diff --git a/tests/crashes/119381.rs b/tests/crashes/119381.rs deleted file mode 100644 index 51d1d084ba2bc..0000000000000 --- a/tests/crashes/119381.rs +++ /dev/null @@ -1,6 +0,0 @@ -//@ known-bug: #119381 - -#![feature(with_negative_coherence)] -trait Trait {} -impl Trait for [(); N] {} -impl Trait for [(); N] {} diff --git a/tests/ui/inference/infer-const-in-param-env.rs b/tests/ui/inference/infer-const-in-param-env.rs new file mode 100644 index 0000000000000..f9ce2a5679385 --- /dev/null +++ b/tests/ui/inference/infer-const-in-param-env.rs @@ -0,0 +1,11 @@ +//! Issue #119381: encountering `ty::ConstKind::Infer(InferConst::Var(_))` inside a `ParamEnv` + +#![feature(with_negative_coherence)] +trait Trait {} +impl Trait for [(); N] {} +impl Trait for [(); N] {} +//~^ conflicting implementations of trait `Trait` for type `[(); _]` +//~| mismatched types +//~^^^^ mismatched types + +fn main() {} diff --git a/tests/ui/inference/infer-const-in-param-env.stderr b/tests/ui/inference/infer-const-in-param-env.stderr new file mode 100644 index 0000000000000..7343610f5e250 --- /dev/null +++ b/tests/ui/inference/infer-const-in-param-env.stderr @@ -0,0 +1,24 @@ +error[E0119]: conflicting implementations of trait `Trait` for type `[(); _]` + --> $DIR/infer-const-in-param-env.rs:6:1 + | +LL | impl Trait for [(); N] {} + | ----------------------------------- first implementation here +LL | impl Trait for [(); N] {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `[(); _]` + +error[E0308]: mismatched types + --> $DIR/infer-const-in-param-env.rs:5:34 + | +LL | impl Trait for [(); N] {} + | ^ expected `usize`, found `u8` + +error[E0308]: mismatched types + --> $DIR/infer-const-in-param-env.rs:6:34 + | +LL | impl Trait for [(); N] {} + | ^ expected `usize`, found `i8` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0119, E0308. +For more information about an error, try `rustc --explain E0119`. diff --git a/tests/ui/type-alias/normalize-const-tys-2.rs b/tests/ui/type-alias/normalize-const-tys-2.rs new file mode 100644 index 0000000000000..65ab42fea6764 --- /dev/null +++ b/tests/ui/type-alias/normalize-const-tys-2.rs @@ -0,0 +1,20 @@ +//! Issue #114456: `deeply_normalize` tys in `check_tys_might_be_eq` +//@ check-pass +#![feature(adt_const_params)] +#![allow(incomplete_features)] + +enum Type {} +trait Trait { type Matrix; } +impl Trait for Type { type Matrix = [usize; 1]; } + +struct Walk::Matrix> {} + +impl Walk<{ [0; 1] }> { + pub const fn new() -> Self { + Self {} + } +} + +fn main() { + let _ = Walk::new(); +} diff --git a/tests/ui/type-alias/normalize-const-tys.rs b/tests/ui/type-alias/normalize-const-tys.rs new file mode 100644 index 0000000000000..2d3b99196a336 --- /dev/null +++ b/tests/ui/type-alias/normalize-const-tys.rs @@ -0,0 +1,17 @@ +//! Issue #114456: `deeply_normalize` tys in `check_tys_might_be_eq` +//@ check-pass +#![feature(adt_const_params, lazy_type_alias)] +#![allow(incomplete_features)] + +type Matrix = [usize; 1]; +struct Walk {} + +impl Walk<{ [0; 1] }> { + pub const fn new() -> Self { + Self {} + } +} + +fn main() { + let _ = Walk::new(); +}