diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 003a950095e4d..d3262bd6a6f96 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -297,7 +297,7 @@ fn do_normalize_predicates<'tcx>( let elaborated_env = if tcx.next_trait_solver_globally() && !tcx.disable_param_env_normalization_hack() { - let elaborated_env = ty::set_aliases_to_rigid(tcx, elaborated_env); + let elaborated_env = ty::set_type_aliases_to_rigid(tcx, elaborated_env); let elaborated_env = set_projection_term_to_non_rigid(tcx, elaborated_env.caller_bounds()); ty::ParamEnv::new(tcx.mk_clauses_from_iter(elaborated_env)) } else { diff --git a/compiler/rustc_type_ir/src/fold.rs b/compiler/rustc_type_ir/src/fold.rs index 14fde5e399994..6a13997ceb0d9 100644 --- a/compiler/rustc_type_ir/src/fold.rs +++ b/compiler/rustc_type_ir/src/fold.rs @@ -584,6 +584,13 @@ where set_aliases_rigidness_with_mode(cx, value, RigidnessFoldMode::AllToRigid) } +pub fn set_type_aliases_to_rigid(cx: I, value: T) -> T +where + T: TypeFoldable, +{ + set_aliases_rigidness_with_mode(cx, value, RigidnessFoldMode::TypeToRigid) +} + fn set_aliases_rigidness_with_mode(cx: I, value: T, mode: RigidnessFoldMode) -> T where T: TypeFoldable, @@ -597,8 +604,9 @@ where } enum RigidnessFoldMode { - AllToNonRigid, AllToRigid, + AllToNonRigid, + TypeToRigid, OpaqueToNonRigid, } @@ -607,6 +615,10 @@ impl RigidnessFoldMode { match self { RigidnessFoldMode::AllToRigid => v.has_non_rigid_aliases(), RigidnessFoldMode::AllToNonRigid => v.has_rigid_aliases(), + RigidnessFoldMode::TypeToRigid => { + v.has_non_rigid_aliases() + && v.has_type_flags(ty::TypeFlags::HAS_ALIAS - ty::TypeFlags::HAS_CONST_ALIAS) + } RigidnessFoldMode::OpaqueToNonRigid => v.has_rigid_aliases() && v.has_opaque_types(), } } @@ -637,7 +649,7 @@ impl TypeFolder for RigidnessFolder { ty::Alias(is_rigid, alias_ty) => { let alias_ty = alias_ty.fold_with(self); match self.mode { - RigidnessFoldMode::AllToRigid => { + RigidnessFoldMode::AllToRigid | RigidnessFoldMode::TypeToRigid => { I::Ty::new_alias(self.cx(), ty::IsRigid::Yes, alias_ty) } RigidnessFoldMode::AllToNonRigid => { @@ -671,7 +683,7 @@ impl TypeFolder for RigidnessFolder { RigidnessFoldMode::AllToNonRigid => { I::Const::new_alias(self.cx(), ty::IsRigid::No, alias_const) } - RigidnessFoldMode::OpaqueToNonRigid => { + RigidnessFoldMode::OpaqueToNonRigid | RigidnessFoldMode::TypeToRigid => { I::Const::new_alias(self.cx(), is_rigid, alias_const) } } diff --git a/tests/ui/traits/next-solver/normalize/dont-mark-const-aliases-as-rigid-in-param-env.rs b/tests/ui/traits/next-solver/normalize/dont-mark-const-aliases-as-rigid-in-param-env.rs new file mode 100644 index 0000000000000..0c3fb9fcbea3c --- /dev/null +++ b/tests/ui/traits/next-solver/normalize/dont-mark-const-aliases-as-rigid-in-param-env.rs @@ -0,0 +1,24 @@ +//@ revisions: old next +//@[next] compile-flags: -Znext-solver +//@ check-pass + +// Regression test for trait-system-refactor-initiative#279. +// The old solver treats unnormalized param env as rigid when normalizing param +// env. However, it eagerly evaluates const aliases in param env before doing +// full normalization. +// We previously treated unevaluated const aliases as rigid in the next solver. + +trait Trait { + type Assoc; +} + +fn foo() +where + [T; 1 + 1]: Trait, + // When normalizing this associated type, we couldn't prove the trait + // predicate. Because the unnormalized trait clause is marked as rigid + // and can't be used as a matching param env candidate. + <[T; 2] as Trait>::Assoc: Copy, +{} + +fn main() {}