diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index 84dbd53de83f2..ac5103c60a1a8 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -2,7 +2,6 @@ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::msg; -use rustc_hir::def::DefKind; use rustc_infer::infer::at::At; use rustc_infer::infer::{InferCtxt, InferOk}; use rustc_infer::traits::{ @@ -461,30 +460,18 @@ impl<'a, 'b, 'tcx> TypeFolder> for AssocTypeNormalizer<'a, 'b, 'tcx _ => return ct.super_fold_with(self), }; - // Note that the AssocConst and Const cases are unreachable on stable, - // unless a `min_generic_const_args` feature gate error has already - // been emitted earlier in compilation. - // - // That's because we can only end up with an Unevaluated ty::Const for a const item - // if it was marked with `type const`. Using this attribute without the mgca - // feature gate causes a parse error. - let ct = match tcx.def_kind(uv.def) { - DefKind::AssocConst { .. } => match tcx.def_kind(tcx.parent(uv.def)) { - DefKind::Trait => self - .normalize_trait_projection(ty::AliasTerm::from_unevaluated_const(tcx, uv)) - .expect_const(), - DefKind::Impl { of_trait: false } => self - .normalize_inherent_projection(ty::AliasTerm::from_unevaluated_const(tcx, uv)) - .expect_const(), - kind => unreachable!( - "unexpected `DefKind` for const alias' resolution's parent def: {:?}", - kind - ), - }, - DefKind::Const { .. } => self - .normalize_free_alias(ty::AliasTerm::from_unevaluated_const(tcx, uv)) - .expect_const(), - DefKind::AnonConst => { + let alias_term = ty::AliasTerm::from_unevaluated_const(tcx, uv); + let ct = match alias_term.kind(tcx) { + ty::AliasTermKind::ProjectionConst { .. } => { + self.normalize_trait_projection(alias_term).expect_const() + } + ty::AliasTermKind::InherentConst { .. } => { + self.normalize_inherent_projection(alias_term).expect_const() + } + ty::AliasTermKind::FreeConst { .. } => { + self.normalize_free_alias(alias_term).expect_const() + } + ty::AliasTermKind::UnevaluatedConst { .. } => { let ct = ct.super_fold_with(self); super::with_replaced_escaping_bound_vars( self.selcx.infcx, @@ -494,7 +481,7 @@ impl<'a, 'b, 'tcx> TypeFolder> for AssocTypeNormalizer<'a, 'b, 'tcx ) } kind => { - unreachable!("unexpected `DefKind` for const alias to resolve to: {:?}", kind) + unreachable!("unexpected `AliasTermKind` for const alias to resolve to: {:?}", kind) } }; diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index e8c5d10c78ce3..4b74464760157 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -4,7 +4,6 @@ use rustc_data_structures::sso::SsoHashMap; use rustc_data_structures::stack::ensure_sufficient_stack; -use rustc_hir::def::DefKind; use rustc_infer::traits::PredicateObligations; use rustc_macros::extension; pub use rustc_middle::traits::query::NormalizationResult; @@ -278,16 +277,17 @@ impl<'a, 'tcx> FallibleTypeFolder> for QueryNormalizer<'a, 'tcx> { _ => return constant.try_super_fold_with(self), }; - let constant = match self.cx().def_kind(uv.def) { - DefKind::AnonConst => crate::traits::with_replaced_escaping_bound_vars( - self.infcx, - &mut self.universes, - constant, - |constant| crate::traits::evaluate_const(&self.infcx, constant, self.param_env), - ), - _ => self - .try_fold_free_or_assoc(ty::AliasTerm::from_unevaluated_const(self.cx(), uv))? - .expect_const(), + let alias_term = ty::AliasTerm::from_unevaluated_const(self.cx(), uv); + let constant = match alias_term.kind(self.cx()) { + ty::AliasTermKind::UnevaluatedConst { .. } => { + crate::traits::with_replaced_escaping_bound_vars( + self.infcx, + &mut self.universes, + constant, + |constant| crate::traits::evaluate_const(&self.infcx, constant, self.param_env), + ) + } + _ => self.try_fold_free_or_assoc(alias_term)?.expect_const(), }; debug!(?constant, ?self.param_env); constant.try_super_fold_with(self) diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index fdf32d32e9058..1719045b44a66 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -6,7 +6,6 @@ use std::iter; use rustc_hir as hir; -use rustc_hir::def::DefKind; use rustc_hir::lang_items::LangItem; use rustc_infer::traits::{ObligationCauseCode, PredicateObligations}; use rustc_middle::bug; @@ -1079,12 +1078,9 @@ impl<'a, 'tcx> TypeVisitor> for WfPredicates<'a, 'tcx> { )); } - if matches!(tcx.def_kind(uv.def), DefKind::AssocConst { .. }) - && tcx.def_kind(tcx.parent(uv.def)) == (DefKind::Impl { of_trait: false }) - { - self.add_wf_preds_for_inherent_projection( - ty::AliasTerm::from_unevaluated_const(tcx, uv), - ); + let alias_term = ty::AliasTerm::from_unevaluated_const(tcx, uv); + if let ty::AliasTermKind::InherentConst { .. } = alias_term.kind(tcx) { + self.add_wf_preds_for_inherent_projection(alias_term); return; // Subtree is handled by above function } else { let obligations = self.nominal_obligations(uv.def, uv.args); diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs index 301cf7dbf1087..6c5e33d977b55 100644 --- a/compiler/rustc_type_ir/src/predicate.rs +++ b/compiler/rustc_type_ir/src/predicate.rs @@ -717,7 +717,13 @@ impl AliasTerm { } pub fn from_unevaluated_const(interner: I, ct: ty::UnevaluatedConst) -> Self { - let kind = interner.alias_term_kind_from_def_id(ct.def.into()); + let mut kind = interner.alias_term_kind_from_def_id(ct.def.into()); + if let AliasTermKind::InherentConst { .. } = kind + && !interner.is_type_const(ct.def.into()) + { + // Only `type const` inherent associated consts use inherent projection args. + kind = AliasTermKind::UnevaluatedConst { def_id: ct.def }; + } AliasTerm::new_from_args(interner, kind, ct.args) } diff --git a/tests/ui/const-generics/generic_const_exprs/inherent-assoc-const-empty-args.rs b/tests/ui/const-generics/generic_const_exprs/inherent-assoc-const-empty-args.rs new file mode 100644 index 0000000000000..13f6f28400154 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/inherent-assoc-const-empty-args.rs @@ -0,0 +1,23 @@ +// Regression test for + +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +struct Test; + +fn new() -> Test +where + [(); N * 1]: Sized, +{ + Test +} + +fn test() -> Test<{ N - 1 }> +where + [(); (N - usize::MAX) * 1]: Sized, +{ + new() + //~^ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/inherent-assoc-const-empty-args.stderr b/tests/ui/const-generics/generic_const_exprs/inherent-assoc-const-empty-args.stderr new file mode 100644 index 0000000000000..9f7578af081c6 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/inherent-assoc-const-empty-args.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/inherent-assoc-const-empty-args.rs:19:5 + | +LL | new() + | ^^^^^ expected `1`, found `usize::MAX` + | + = note: expected constant `1` + found constant `usize::MAX` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`.