From 8777302deed79ba69a44e62c1f8faf9801b0683b Mon Sep 17 00:00:00 2001 From: khyperia <953151+khyperia@users.noreply.github.com> Date: Fri, 29 May 2026 07:57:04 +0200 Subject: [PATCH] introduce UnevaluatedConstKind --- compiler/rustc_borrowck/src/type_check/mod.rs | 8 +- .../rustc_codegen_ssa/src/mir/constant.rs | 5 +- .../rustc_hir_analysis/src/check/check.rs | 2 +- .../rustc_hir_analysis/src/check/wfcheck.rs | 8 +- .../src/collect/predicates_of.rs | 6 +- .../src/hir_ty_lowering/mod.rs | 36 +++++-- .../src/infer/relate/generalize.rs | 16 +-- compiler/rustc_middle/src/mir/consts.rs | 8 +- .../rustc_middle/src/mir/interpret/queries.rs | 6 +- compiler/rustc_middle/src/mir/pretty.rs | 6 +- .../rustc_middle/src/ty/abstract_const.rs | 18 ++-- compiler/rustc_middle/src/ty/consts.rs | 4 +- .../src/ty/context/impl_interner.rs | 22 ++++- compiler/rustc_middle/src/ty/mod.rs | 8 +- compiler/rustc_middle/src/ty/print/pretty.rs | 23 ++--- compiler/rustc_middle/src/ty/util.rs | 2 +- .../src/builder/expr/as_constant.rs | 6 +- compiler/rustc_mir_build/src/builder/scope.rs | 2 +- .../src/thir/pattern/const_to_pat.rs | 19 ++-- .../rustc_mir_build/src/thir/pattern/mod.rs | 9 +- .../src/solve/alias_relate.rs | 10 +- .../rustc_next_trait_solver/src/solve/mod.rs | 4 +- .../src/solve/normalizes_to/mod.rs | 5 +- .../src/unstable/convert/stable/ty.rs | 2 +- compiler/rustc_symbol_mangling/src/v0.rs | 4 +- .../traits/fulfillment_errors.rs | 13 ++- .../src/solve/fulfill/derive_errors.rs | 8 +- .../src/traits/auto_trait.rs | 2 +- .../src/traits/const_evaluatable.rs | 15 +-- .../src/traits/dyn_compatibility.rs | 17 ++-- .../src/traits/fulfill.rs | 14 +-- .../rustc_trait_selection/src/traits/mod.rs | 28 +++--- .../src/traits/normalize.rs | 36 +++---- .../src/traits/project.rs | 2 +- .../src/traits/query/normalize.rs | 24 +++-- .../src/traits/select/mod.rs | 14 +-- .../src/traits/structural_normalize.rs | 2 +- .../rustc_trait_selection/src/traits/wf.rs | 14 +-- compiler/rustc_ty_utils/src/consts.rs | 6 +- compiler/rustc_type_ir/src/const_kind.rs | 53 +++++++++- compiler/rustc_type_ir/src/inherent.rs | 6 +- compiler/rustc_type_ir/src/interner.rs | 5 + compiler/rustc_type_ir/src/predicate.rs | 97 +++++++++++++------ compiler/rustc_type_ir/src/relate.rs | 10 +- src/librustdoc/clean/utils.rs | 6 +- .../issue_99325.main.built.after.32bit.mir | 2 +- .../issue_99325.main.built.after.64bit.mir | 2 +- tests/ui/offset-of/inside-array-length.stderr | 2 +- 48 files changed, 385 insertions(+), 232 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 13983f349d6a5..b1cf7546878ab 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1760,9 +1760,11 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { let tcx = self.tcx(); let maybe_uneval = match constant.const_ { Const::Ty(_, ct) => match ct.kind() { - ty::ConstKind::Unevaluated(uv) => { - Some(UnevaluatedConst { def: uv.def, args: uv.args, promoted: None }) - } + ty::ConstKind::Unevaluated(uv) => Some(UnevaluatedConst { + def: uv.kind.def_id(), + args: uv.args, + promoted: None, + }), _ => None, }, Const::Unevaluated(uv, _) => Some(uv), diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs index abdac4c7c3721..d4747c1cbafc9 100644 --- a/compiler/rustc_codegen_ssa/src/mir/constant.rs +++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs @@ -38,8 +38,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { &self, constant: &mir::ConstOperand<'tcx>, ) -> Result, Ty<'tcx>>, ErrorHandled> { + let tcx = self.cx.tcx(); let uv = match self.monomorphize(constant.const_) { - mir::Const::Unevaluated(uv, _) => uv.shrink(), + mir::Const::Unevaluated(uv, _) => uv.shrink(tcx), mir::Const::Ty(_, c) => match c.kind() { // A constant that came from a const generic but was then used as an argument to // old-style simd_shuffle (passing as argument instead of as a generic param). @@ -57,7 +58,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { other => span_bug!(constant.span, "{other:#?}"), }; let uv = self.monomorphize(uv); - self.cx.tcx().const_eval_resolve_for_typeck(self.cx.typing_env(), uv, constant.span) + tcx.const_eval_resolve_for_typeck(self.cx.typing_env(), uv, constant.span) } /// process constant containing SIMD shuffle indices & constant vectors diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index f90311c66d600..14759ad919e24 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -776,7 +776,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), // need to store default and type of default let ct = tcx.const_param_default(param.def_id).skip_binder(); if let ty::ConstKind::Unevaluated(uv) = ct.kind() { - tcx.ensure_ok().type_of(uv.def); + tcx.ensure_ok().type_of(uv.kind.def_id()); } } } diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index dd506dd2b7fc9..f495df360e6d9 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1535,9 +1535,11 @@ pub(super) fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, def_id: | ty::ConstKind::Bound(_, _) => unreachable!(), ty::ConstKind::Error(_) | ty::ConstKind::Expr(_) => continue, ty::ConstKind::Value(cv) => cv.ty, - ty::ConstKind::Unevaluated(uv) => { - infcx.tcx.type_of(uv.def).instantiate(infcx.tcx, uv.args).skip_norm_wip() - } + ty::ConstKind::Unevaluated(uv) => infcx + .tcx + .type_of(uv.kind.def_id()) + .instantiate(infcx.tcx, uv.args) + .skip_norm_wip(), ty::ConstKind::Param(param_ct) => { param_ct.find_const_ty_from_env(wfcx.param_env) } diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index ad46f011a79cb..cf29a76418792 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -435,7 +435,7 @@ fn const_evaluatable_predicates_of<'tcx>( impl<'tcx> TypeVisitor> for ConstCollector<'tcx> { fn visit_const(&mut self, c: ty::Const<'tcx>) { if let ty::ConstKind::Unevaluated(uv) = c.kind() { - if let Some(local) = uv.def.as_local() + if let Some(local) = uv.kind.def_id().as_local() && is_const_param_default(self.tcx, local) { // Do not look into const param defaults, @@ -449,11 +449,11 @@ fn const_evaluatable_predicates_of<'tcx>( } // Skip type consts as mGCA doesn't support evaluatable clauses. - if self.tcx.is_type_const(uv.def) { + if self.tcx.is_type_const(uv.kind.def_id()) { return; } - let span = self.tcx.def_span(uv.def); + let span = self.tcx.def_span(uv.kind.def_id()); self.preds.insert((ty::ClauseKind::ConstEvaluatable(c).upcast(self.tcx), span)); } } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 5a86e8186a5aa..f46569549bd9d 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -1518,7 +1518,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { )? { TypeRelativePath::AssocItem(def_id, args) => { self.require_type_const_attribute(def_id, span)?; - let ct = Const::new_unevaluated(tcx, ty::UnevaluatedConst::new(def_id, args)); + let ct = Const::new_unevaluated( + tcx, + ty::UnevaluatedConst::new( + tcx, + ty::UnevaluatedConstKind::new_from_def_id(tcx, def_id), + args, + ), + ); let ct = self.check_param_uses_if_mcg(ct, span, false); Ok(ct) } @@ -2008,6 +2015,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { trait_segment: Option<&hir::PathSegment<'tcx>>, item_segment: &hir::PathSegment<'tcx>, ) -> Result, ErrorGuaranteed> { + let tcx = self.tcx(); let (item_def_id, item_args) = self.lower_resolved_assoc_item_path( span, opt_self_ty, @@ -2017,8 +2025,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ty::AssocTag::Const, )?; self.require_type_const_attribute(item_def_id, span)?; - let uv = ty::UnevaluatedConst::new(item_def_id, item_args); - Ok(Const::new_unevaluated(self.tcx(), uv)) + let uv = ty::UnevaluatedConst::new( + tcx, + ty::UnevaluatedConstKind::new_from_def_id(tcx, item_def_id), + item_args, + ); + Ok(Const::new_unevaluated(tcx, uv)) } /// Lower a [resolved][hir::QPath::Resolved] (type-level) associated item path. @@ -2860,7 +2872,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let _ = self .prohibit_generic_args(leading_segments.iter(), GenericsArgsErrExtend::None); let args = self.lower_generic_args_of_path_segment(span, did, segment); - ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst::new(did, args)) + ty::Const::new_unevaluated( + tcx, + ty::UnevaluatedConst::new( + tcx, + ty::UnevaluatedConstKind::new_from_def_id(tcx, did), + args, + ), + ) } Res::Def(DefKind::Ctor(ctor_of, CtorKind::Const), did) => { assert_eq!(opt_self_ty, None); @@ -2984,10 +3003,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { Some(v) => v, None => ty::Const::new_unevaluated( tcx, - ty::UnevaluatedConst { - def: anon.def_id.to_def_id(), - args: ty::GenericArgs::identity_for_item(tcx, anon.def_id.to_def_id()), - }, + ty::UnevaluatedConst::new( + tcx, + ty::UnevaluatedConstKind::Anon { def_id: anon.def_id.to_def_id() }, + ty::GenericArgs::identity_for_item(tcx, anon.def_id.to_def_id()), + ), ), } } diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs index 3d2d617cfdb29..9b928e8fc9e99 100644 --- a/compiler/rustc_infer/src/infer/relate/generalize.rs +++ b/compiler/rustc_infer/src/infer/relate/generalize.rs @@ -184,7 +184,7 @@ impl<'tcx> InferCtxt<'tcx> { relation.register_predicates([ty::PredicateKind::AliasRelate(lhs, rhs, direction)]); } else { - let Some(source_alias) = source_term.to_alias_term(self.tcx) else { + let Some(source_alias) = source_term.to_alias_term() else { bug!("generalized `{source_term:?} to infer, not an alias"); }; match source_alias.kind(self.tcx) { @@ -207,7 +207,7 @@ impl<'tcx> InferCtxt<'tcx> { } ty::AliasTermKind::InherentConst { .. } | ty::AliasTermKind::FreeConst { .. } - | ty::AliasTermKind::UnevaluatedConst { .. } => { + | ty::AliasTermKind::AnonConst { .. } => { return Err(TypeError::CyclicConst(source_term.expect_const())); } } @@ -701,6 +701,7 @@ impl<'tcx> TypeRelation> for Generalizer<'_, 'tcx> { c: ty::Const<'tcx>, c2: ty::Const<'tcx>, ) -> RelateResult<'tcx, ty::Const<'tcx>> { + let tcx = self.cx(); assert_eq!(c, c2); // we are misusing TypeRelation here; both LHS and RHS ought to be == match c.kind() { @@ -741,7 +742,7 @@ impl<'tcx> TypeRelation> for Generalizer<'_, 'tcx> { { variable_table.union(vid, new_var_id); } - Ok(ty::Const::new_var(self.cx(), new_var_id)) + Ok(ty::Const::new_var(tcx, new_var_id)) } } } @@ -755,19 +756,18 @@ impl<'tcx> TypeRelation> for Generalizer<'_, 'tcx> { // Hack: Fall back to old behavior if GCE is enabled (it used to just be the Yes // path), as doing this new No path breaks some GCE things. I expect GCE to be // ripped out soon so this shouldn't matter soon. - StructurallyRelateAliases::No if !self.cx().features().generic_const_exprs() => { - self.generalize_alias_term(ty::AliasTerm::from_unevaluated_const(self.cx(), uv)) - .map(|v| v.expect_const()) + StructurallyRelateAliases::No if !tcx.features().generic_const_exprs() => { + self.generalize_alias_term(uv.into()).map(|v| v.expect_const()) } _ => { - let ty::UnevaluatedConst { def, args } = uv; + let ty::UnevaluatedConst { kind, args, .. } = uv; let args = self.relate_with_variance( ty::Invariant, ty::VarianceDiagInfo::default(), args, args, )?; - Ok(ty::Const::new_unevaluated(self.cx(), ty::UnevaluatedConst { def, args })) + Ok(ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst::new(tcx, kind, args))) } }, ty::ConstKind::Placeholder(placeholder) => { diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs index 2e9cd31a13de0..39c73350f7e41 100644 --- a/compiler/rustc_middle/src/mir/consts.rs +++ b/compiler/rustc_middle/src/mir/consts.rs @@ -467,9 +467,13 @@ pub struct UnevaluatedConst<'tcx> { impl<'tcx> UnevaluatedConst<'tcx> { #[inline] - pub fn shrink(self) -> ty::UnevaluatedConst<'tcx> { + pub fn shrink(self, tcx: TyCtxt<'tcx>) -> ty::UnevaluatedConst<'tcx> { assert_eq!(self.promoted, None); - ty::UnevaluatedConst { def: self.def, args: self.args } + ty::UnevaluatedConst::new( + tcx, + ty::UnevaluatedConstKind::new_from_def_id(tcx, self.def), + self.args, + ) } } diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs index 00ac8e66cda75..6bd1bbe3af20c 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs @@ -103,7 +103,7 @@ impl<'tcx> TyCtxt<'tcx> { bug!("did not expect inference variables here"); } - let cid = match ty::Instance::try_resolve(self, typing_env, ct.def, ct.args) { + let cid = match ty::Instance::try_resolve(self, typing_env, ct.kind.def_id(), ct.args) { Ok(Some(instance)) => GlobalId { instance, promoted: None }, // For errors during resolution, we deliberately do not point at the usage site of the constant, // since for these errors the place the constant is used shouldn't matter. @@ -138,11 +138,11 @@ impl<'tcx> TyCtxt<'tcx> { { let mir_body = self.mir_for_ctfe(cid.instance.def_id()); if mir_body.is_polymorphic { - let Some(local_def_id) = ct.def.as_local() else { return }; + let Some(local_def_id) = ct.kind.def_id().as_local() else { return }; self.emit_node_span_lint( lint::builtin::CONST_EVALUATABLE_UNCHECKED, self.local_def_id_to_hir_id(local_def_id), - self.def_span(ct.def), + self.def_span(ct.kind.def_id()), rustc_errors::DiagDecorator(|lint| { lint.primary_message( "cannot use constants which depend on generic parameters in types", diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 60c829311c4b1..c4b26e6c206fe 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -1429,7 +1429,11 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> { Const::Ty(_, ct) => match ct.kind() { ty::ConstKind::Param(p) => format!("ty::Param({p})"), ty::ConstKind::Unevaluated(uv) => { - format!("ty::Unevaluated({}, {:?})", self.tcx.def_path_str(uv.def), uv.args,) + format!( + "ty::Unevaluated({}, {:?})", + self.tcx.def_path_str(uv.kind.def_id()), + uv.args, + ) } ty::ConstKind::Value(cv) => { format!("ty::Valtree({})", fmt_valtree(&cv)) diff --git a/compiler/rustc_middle/src/ty/abstract_const.rs b/compiler/rustc_middle/src/ty/abstract_const.rs index c6fa6ebed7928..984c9ec48321d 100644 --- a/compiler/rustc_middle/src/ty/abstract_const.rs +++ b/compiler/rustc_middle/src/ty/abstract_const.rs @@ -52,15 +52,17 @@ impl<'tcx> TyCtxt<'tcx> { } fn fold_const(&mut self, c: Const<'tcx>) -> Const<'tcx> { let ct = match c.kind() { - ty::ConstKind::Unevaluated(uv) => match self.tcx.thir_abstract_const(uv.def) { - Err(e) => ty::Const::new_error(self.tcx, e), - Ok(Some(bac)) => { - let args = self.tcx.erase_and_anonymize_regions(uv.args); - let bac = bac.instantiate(self.tcx, args).skip_norm_wip(); - return bac.fold_with(self); + ty::ConstKind::Unevaluated(uv) => { + match self.tcx.thir_abstract_const(uv.kind.def_id()) { + Err(e) => ty::Const::new_error(self.tcx, e), + Ok(Some(bac)) => { + let args = self.tcx.erase_and_anonymize_regions(uv.args); + let bac = bac.instantiate(self.tcx, args).skip_norm_wip(); + return bac.fold_with(self); + } + Ok(None) => c, } - Ok(None) => c, - }, + } _ => c, }; ct.super_fold_with(self) diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 7421024bba0cc..30d9a9fb1650c 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -22,9 +22,10 @@ pub use valtree::*; pub type ConstKind<'tcx> = ir::ConstKind>; pub type UnevaluatedConst<'tcx> = ir::UnevaluatedConst>; +pub type UnevaluatedConstKind<'tcx> = ir::UnevaluatedConstKind>; #[cfg(target_pointer_width = "64")] -rustc_data_structures::static_assert_size!(ConstKind<'_>, 24); +rustc_data_structures::static_assert_size!(ConstKind<'_>, 32); #[derive(Copy, Clone, PartialEq, Eq, Hash, StableHash)] #[rustc_pass_by_value] @@ -107,7 +108,6 @@ impl<'tcx> Const<'tcx> { #[inline] pub fn new_unevaluated(tcx: TyCtxt<'tcx>, uv: ty::UnevaluatedConst<'tcx>) -> Const<'tcx> { - tcx.debug_assert_args_compatible(uv.def, uv.args); Const::new(tcx, ty::ConstKind::Unevaluated(uv)) } diff --git a/compiler/rustc_middle/src/ty/context/impl_interner.rs b/compiler/rustc_middle/src/ty/context/impl_interner.rs index 7f1eeda4ad1d6..bc8b83e460080 100644 --- a/compiler/rustc_middle/src/ty/context/impl_interner.rs +++ b/compiler/rustc_middle/src/ty/context/impl_interner.rs @@ -219,6 +219,26 @@ impl<'tcx> Interner for TyCtxt<'tcx> { } } + fn unevaluated_const_kind_from_def_id( + self, + def_id: Self::DefId, + ) -> ty::UnevaluatedConstKind<'tcx> { + match self.def_kind(def_id) { + DefKind::AssocConst { .. } => { + if let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(def_id)) { + ty::UnevaluatedConstKind::Inherent { def_id } + } else { + ty::UnevaluatedConstKind::Projection { def_id } + } + } + DefKind::Const { .. } => ty::UnevaluatedConstKind::Free { def_id }, + DefKind::AnonConst | DefKind::InlineConst | DefKind::Ctor(_, CtorKind::Const) => { + ty::UnevaluatedConstKind::Anon { def_id } + } + kind => bug!("unexpected DefKind in UnevaluatedConst: {kind:?}"), + } + } + fn alias_term_kind_from_def_id(self, def_id: DefId) -> ty::AliasTermKind<'tcx> { match self.def_kind(def_id) { DefKind::AssocTy => { @@ -239,7 +259,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> { DefKind::TyAlias => ty::AliasTermKind::FreeTy { def_id }, DefKind::Const { .. } => ty::AliasTermKind::FreeConst { def_id }, DefKind::AnonConst | DefKind::Ctor(_, CtorKind::Const) => { - ty::AliasTermKind::UnevaluatedConst { def_id } + ty::AliasTermKind::AnonConst { def_id } } kind => bug!("unexpected DefKind in AliasTy: {kind:?}"), } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 74f9e75fb48c0..0e93dad1a692f 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -79,8 +79,8 @@ pub use self::closure::{ }; pub use self::consts::{ AtomicOrdering, Const, ConstInt, ConstKind, ConstToValTreeResult, Expr, ExprKind, - LitToConstInput, ScalarInt, SimdAlign, UnevaluatedConst, ValTree, ValTreeKindExt, Value, - const_lit_matches_ty, + LitToConstInput, ScalarInt, SimdAlign, UnevaluatedConst, UnevaluatedConstKind, ValTree, + ValTreeKindExt, Value, const_lit_matches_ty, }; pub use self::context::{ CtxtInterners, CurrentGcx, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed, tls, @@ -669,14 +669,14 @@ impl<'tcx> Term<'tcx> { } } - pub fn to_alias_term(self, tcx: TyCtxt<'tcx>) -> Option> { + pub fn to_alias_term(self) -> Option> { match self.kind() { TermKind::Ty(ty) => match *ty.kind() { ty::Alias(alias_ty) => Some(alias_ty.into()), _ => None, }, TermKind::Const(ct) => match ct.kind() { - ConstKind::Unevaluated(uv) => Some(AliasTerm::from_unevaluated_const(tcx, uv)), + ConstKind::Unevaluated(uv) => Some(uv.into()), _ => None, }, } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index daead99b977c1..742b25766642b 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1561,14 +1561,16 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { } match ct.kind() { - ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args }) => { - match self.tcx().def_kind(def) { - DefKind::Const { .. } | DefKind::AssocConst { .. } => { - self.pretty_print_value_path(def, args)?; + ty::ConstKind::Unevaluated(ty::UnevaluatedConst { kind, args, .. }) => { + match kind { + ty::UnevaluatedConstKind::Projection { def_id } + | ty::UnevaluatedConstKind::Inherent { def_id } + | ty::UnevaluatedConstKind::Free { def_id } => { + self.pretty_print_value_path(def_id, args)?; } - DefKind::AnonConst => { - if def.is_local() - && let span = self.tcx().def_span(def) + ty::UnevaluatedConstKind::Anon { def_id } => { + if def_id.is_local() + && let span = self.tcx().def_span(def_id) && let Ok(snip) = self.tcx().sess.source_map().span_to_snippet(span) { write!(self, "{snip}")?; @@ -1583,12 +1585,11 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { write!( self, "{}::{}", - self.tcx().crate_name(def.krate), - self.tcx().def_path(def).to_string_no_crate_verbose() + self.tcx().crate_name(def_id.krate), + self.tcx().def_path(def_id).to_string_no_crate_verbose() )?; } } - defkind => bug!("`{:?}` has unexpected defkind {:?}", ct, defkind), } } ty::ConstKind::Infer(infer_ct) => match infer_ct { @@ -3169,7 +3170,7 @@ define_print! { ty::AliasTermKind::FreeTy { def_id } | ty::AliasTermKind::FreeConst { def_id } | ty::AliasTermKind::OpaqueTy { def_id } - | ty::AliasTermKind::UnevaluatedConst { def_id } + | ty::AliasTermKind::AnonConst { def_id } | ty::AliasTermKind::ProjectionConst { def_id } => { p.print_def_path(def_id, self.args)?; } diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 99da2da391151..9f6d1170a85f1 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -931,7 +931,7 @@ impl<'tcx> TyCtxt<'tcx> { | ty::AliasTermKind::InherentConst { .. } | ty::AliasTermKind::FreeTy { .. } | ty::AliasTermKind::FreeConst { .. } - | ty::AliasTermKind::UnevaluatedConst { .. } + | ty::AliasTermKind::AnonConst { .. } | ty::AliasTermKind::ProjectionConst { .. } => None, } } diff --git a/compiler/rustc_mir_build/src/builder/expr/as_constant.rs b/compiler/rustc_mir_build/src/builder/expr/as_constant.rs index c67d99a8eb7de..76360ee6c5b46 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_constant.rs @@ -72,7 +72,11 @@ pub(crate) fn as_constant_inner<'tcx>( ExprKind::NamedConst { def_id, args, ref user_ty } => { let user_ty = user_ty.as_ref().and_then(push_cuta); if tcx.is_type_const(def_id) { - let uneval = ty::UnevaluatedConst::new(def_id, args); + let uneval = ty::UnevaluatedConst::new( + tcx, + ty::UnevaluatedConstKind::new_from_def_id(tcx, def_id), + args, + ); let ct = ty::Const::new_unevaluated(tcx, uneval); let const_ = Const::Ty(ty, ct); diff --git a/compiler/rustc_mir_build/src/builder/scope.rs b/compiler/rustc_mir_build/src/builder/scope.rs index 3343bec30caf5..22c5ab7ba172f 100644 --- a/compiler/rustc_mir_build/src/builder/scope.rs +++ b/compiler/rustc_mir_build/src/builder/scope.rs @@ -846,7 +846,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ) -> Result<(ty::ValTree<'tcx>, Ty<'tcx>), interpret::ErrorHandled> { assert!(!constant.const_.ty().has_param()); let (uv, ty) = match constant.const_ { - mir::Const::Unevaluated(uv, ty) => (uv.shrink(), ty), + mir::Const::Unevaluated(uv, ty) => (uv.shrink(self.tcx), ty), mir::Const::Ty(_, c) => match c.kind() { // A constant that came from a const generic but was then used as an argument to // old-style simd_shuffle (passing as argument instead of as a generic param). diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 0c6e1b83c9535..2f2126c9dcc67 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -73,16 +73,18 @@ impl<'tcx> ConstToPat<'tcx> { /// We errored. Signal that in the pattern, so that follow up errors can be silenced. fn mk_err(&self, mut err: Diag<'_>, ty: Ty<'tcx>) -> Box> { if let ty::ConstKind::Unevaluated(uv) = self.c.kind() { - let def_kind = self.tcx.def_kind(uv.def); - if let hir::def::DefKind::AssocConst { .. } = def_kind - && let Some(def_id) = uv.def.as_local() + if let ty::UnevaluatedConstKind::Projection { def_id } + | ty::UnevaluatedConstKind::Inherent { def_id } = uv.kind + && let Some(def_id) = def_id.as_local() { // Include the container item in the output. err.span_label(self.tcx.def_span(self.tcx.local_parent(def_id)), ""); } - if let hir::def::DefKind::Const { .. } | hir::def::DefKind::AssocConst { .. } = def_kind + if let ty::UnevaluatedConstKind::Projection { def_id } + | ty::UnevaluatedConstKind::Inherent { def_id } + | ty::UnevaluatedConstKind::Free { def_id } = uv.kind { - err.span_label(self.tcx.def_span(uv.def), msg!("constant defined here")); + err.span_label(self.tcx.def_span(def_id), msg!("constant defined here")); } } Box::new(Pat { span: self.span, ty, kind: PatKind::Error(err.emit()), extra: None }) @@ -117,8 +119,9 @@ impl<'tcx> ConstToPat<'tcx> { // We've emitted an error on the original const, it would be redundant to complain // on its use as well. if let ty::ConstKind::Unevaluated(uv) = self.c.kind() - && let hir::def::DefKind::Const { .. } | hir::def::DefKind::AssocConst { .. } = - self.tcx.def_kind(uv.def) + && let ty::UnevaluatedConstKind::Projection { .. } + | ty::UnevaluatedConstKind::Inherent { .. } + | ty::UnevaluatedConstKind::Free { .. } = uv.kind { err.downgrade_to_delayed_bug(); } @@ -183,7 +186,7 @@ impl<'tcx> ConstToPat<'tcx> { // Mark the pattern to indicate that it is the result of lowering a named // constant. This is used for diagnostics. - thir_pat.extra.get_or_insert_default().expanded_const = Some(uv.def); + thir_pat.extra.get_or_insert_default().expanded_const = Some(uv.kind.def_id()); thir_pat } diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index d59fce3ee0658..d826a7ed1f30a 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -657,7 +657,14 @@ impl<'tcx, 'ptcx> PatCtxt<'tcx, 'ptcx> { let args = self.typeck_results.node_args(id); // FIXME(mgca): we will need to special case IACs here to have type system compatible // generic args, instead of how we represent them in body expressions. - let c = ty::Const::new_unevaluated(self.tcx, ty::UnevaluatedConst { def: def_id, args }); + let c = ty::Const::new_unevaluated( + self.tcx, + ty::UnevaluatedConst::new( + self.tcx, + ty::UnevaluatedConstKind::new_from_def_id(self.tcx, def_id), + args, + ), + ); let mut pattern = self.const_to_pat(c, ty, id, span); // If this is an associated constant with an explicit user-written diff --git a/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs b/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs index 47d33985f9d36..b7e2101577eb2 100644 --- a/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs +++ b/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs @@ -41,14 +41,14 @@ where // `{type error}` if the alias still contains infer vars, so we also // accept alias-relate goals where one of the terms is an error. debug_assert!( - lhs.to_alias_term(self.cx()).is_some() - || rhs.to_alias_term(self.cx()).is_some() + lhs.to_alias_term().is_some() + || rhs.to_alias_term().is_some() || lhs.is_error() || rhs.is_error() ); // Structurally normalize the lhs. - let lhs = if let Some(alias) = lhs.to_alias_term(self.cx()) { + let lhs = if let Some(alias) = lhs.to_alias_term() { let term = self.next_term_infer_of_kind(lhs); self.add_goal( GoalSource::TypeRelating, @@ -60,7 +60,7 @@ where }; // Structurally normalize the rhs. - let rhs = if let Some(alias) = rhs.to_alias_term(self.cx()) { + let rhs = if let Some(alias) = rhs.to_alias_term() { let term = self.next_term_infer_of_kind(rhs); self.add_goal( GoalSource::TypeRelating, @@ -87,7 +87,7 @@ where ty::AliasRelationDirection::Equate => ty::Invariant, ty::AliasRelationDirection::Subtype => ty::Covariant, }; - match (lhs.to_alias_term(self.cx()), rhs.to_alias_term(self.cx())) { + match (lhs.to_alias_term(), rhs.to_alias_term()) { (None, None) => { self.relate(param_env, lhs, variance, rhs)?; self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs index fbd6bdfa0a989..04da730477bc2 100644 --- a/compiler/rustc_next_trait_solver/src/solve/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs @@ -247,7 +247,7 @@ where .map_err(Into::into); } ty::ConstKind::Unevaluated(uv) => { - self.cx().type_of(uv.def.into()).instantiate(self.cx(), uv.args).skip_norm_wip() + self.cx().type_of(uv.kind.def_id()).instantiate(self.cx(), uv.args).skip_norm_wip() } ty::ConstKind::Expr(_) => unimplemented!( "`feature(generic_const_exprs)` is not supported in the new trait solver" @@ -368,7 +368,7 @@ where param_env: I::ParamEnv, term: I::Term, ) -> Result { - if let Some(_) = term.to_alias_term(self.cx()) { + if let Some(_) = term.to_alias_term() { let normalized_term = self.next_term_infer_of_kind(term); let alias_relate_goal = Goal::new( self.cx(), diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index e9a4d7e5919ad..afec80e4b873a 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -49,7 +49,7 @@ where ty::AliasTermKind::FreeTy { .. } | ty::AliasTermKind::FreeConst { .. } => { self.normalize_free_alias(goal).map_err(Into::into) } - ty::AliasTermKind::UnevaluatedConst { def_id } => { + ty::AliasTermKind::AnonConst { def_id } => { self.normalize_anon_const(goal, def_id).map_err(Into::into) } } @@ -416,7 +416,8 @@ where } ty::AliasTermKind::ProjectionConst { .. } => { let uv = ty::UnevaluatedConst::new( - target_item_def_id.into().try_into().unwrap(), + cx, + ty::UnevaluatedConstKind::new_from_def_id(cx, target_item_def_id.into()), target_args, ); return ecx.evaluate_const_and_instantiate_normalizes_to_term(goal, uv); diff --git a/compiler/rustc_public/src/unstable/convert/stable/ty.rs b/compiler/rustc_public/src/unstable/convert/stable/ty.rs index c4f1da14da23e..925d4a5b40b20 100644 --- a/compiler/rustc_public/src/unstable/convert/stable/ty.rs +++ b/compiler/rustc_public/src/unstable/convert/stable/ty.rs @@ -541,7 +541,7 @@ impl<'tcx> Stable<'tcx> for ty::Const<'tcx> { } ty::ConstKind::Param(param) => crate::ty::TyConstKind::Param(param.stable(tables, cx)), ty::ConstKind::Unevaluated(uv) => crate::ty::TyConstKind::Unevaluated( - tables.const_def(uv.def), + tables.const_def(uv.kind.def_id()), uv.args.stable(tables, cx), ), ty::ConstKind::Error(_) => unreachable!(), diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 61c1c83c3f8f6..27eef4cba264b 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -690,8 +690,8 @@ impl<'tcx> Printer<'tcx> for V0SymbolMangler<'tcx> { // We may still encounter unevaluated consts due to the printing // logic sometimes passing identity-substituted impl headers. - ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args, .. }) => { - return self.print_def_path(def, args); + ty::ConstKind::Unevaluated(ty::UnevaluatedConst { kind, args, .. }) => { + return self.print_def_path(kind.def_id(), args); } ty::ConstKind::Expr(_) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 4d051a370c065..4ae7d126a487f 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -1651,7 +1651,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } }; - if let Some(lhs) = lhs.to_alias_term(self.tcx) + if let Some(lhs) = lhs.to_alias_term() && let ty::AliasTermKind::ProjectionTy { .. } | ty::AliasTermKind::ProjectionConst { .. } = lhs.kind(self.tcx) && let Some((better_type_err, expected_term)) = @@ -1661,7 +1661,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { Some((lhs, self.resolve_vars_if_possible(expected_term), rhs)), better_type_err, ) - } else if let Some(rhs) = rhs.to_alias_term(self.tcx) + } else if let Some(rhs) = rhs.to_alias_term() && let ty::AliasTermKind::ProjectionTy { .. } | ty::AliasTermKind::ProjectionConst { .. } = rhs.kind(self.tcx) && let Some((better_type_err, expected_term)) = @@ -3732,10 +3732,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ty::ConstKind::Unevaluated(uv) => { let mut err = self.dcx().struct_span_err(span, "unconstrained generic constant"); - let const_span = self.tcx.def_span(uv.def); + let const_span = self.tcx.def_span(uv.kind.def_id()); - let const_ty = - self.tcx.type_of(uv.def).instantiate(self.tcx, uv.args).skip_norm_wip(); + let const_ty = self + .tcx + .type_of(uv.kind.def_id()) + .instantiate(self.tcx, uv.args) + .skip_norm_wip(); let cast = if const_ty != self.tcx.types.usize { " as usize" } else { "" }; let msg = "try adding a `where` bound"; match self.tcx.sess.source_map().span_to_snippet(const_span) { diff --git a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs index 12dfe730aa303..1aa9af417ae50 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs @@ -34,9 +34,11 @@ pub(super) fn fulfillment_error_for_no_solution<'tcx>( } ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, expected_ty)) => { let ct_ty = match ct.kind() { - ty::ConstKind::Unevaluated(uv) => { - infcx.tcx.type_of(uv.def).instantiate(infcx.tcx, uv.args).skip_norm_wip() - } + ty::ConstKind::Unevaluated(uv) => infcx + .tcx + .type_of(uv.kind.def_id()) + .instantiate(infcx.tcx, uv.args) + .skip_norm_wip(), ty::ConstKind::Param(param_ct) => { param_ct.find_const_ty_from_env(obligation.param_env) } diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index af104a56202b0..3da4e84e89837 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -774,7 +774,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { if let Err(EvaluateConstErr::InvalidConstParamTy(_)) = ct { self.tcx.dcx().emit_err(UnableToConstructConstantValue { - span: self.tcx.def_span(unevaluated.def), + span: self.tcx.def_span(unevaluated.kind.def_id()), unevaluated, }); } diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 45f30cd14c672..90e795f1391a4 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -9,7 +9,6 @@ //! `thir_abstract_const` which can then be checked for structural equality with other //! generic constants mentioned in the `caller_bounds` of the current environment. -use rustc_hir::def::DefKind; use rustc_infer::infer::InferCtxt; use rustc_middle::bug; use rustc_middle::traits::ObligationCause; @@ -43,11 +42,13 @@ pub fn is_const_evaluatable<'tcx>( if tcx.features().generic_const_exprs() { let ct = tcx.expand_abstract_consts(unexpanded_ct); - let is_anon_ct = if let ty::ConstKind::Unevaluated(uv) = ct.kind() { - tcx.def_kind(uv.def) == DefKind::AnonConst - } else { - false - }; + let is_anon_ct = matches!( + ct.kind(), + ty::ConstKind::Unevaluated(ty::UnevaluatedConst { + kind: ty::UnevaluatedConstKind::Anon { .. }, + .. + }) + ); if !is_anon_ct { if satisfied_from_param_env(tcx, infcx, ct, param_env) { @@ -116,7 +117,7 @@ pub fn is_const_evaluatable<'tcx>( tcx.dcx() .struct_span_fatal( // Slightly better span than just using `span` alone - if span == DUMMY_SP { tcx.def_span(uv.def) } else { span }, + if span == DUMMY_SP { tcx.def_span(uv.kind.def_id()) } else { span }, "failed to evaluate generic const expression", ) .with_note("the crate this constant originates from uses `#![feature(generic_const_exprs)]`") diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index a018a150a7067..1d3c9be245a5a 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -7,7 +7,6 @@ use std::ops::ControlFlow; use rustc_errors::FatalError; -use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_hir::{self as hir, LangItem}; use rustc_middle::query::Providers; @@ -887,13 +886,15 @@ impl<'tcx> TypeVisitor> for IllegalSelfTypeVisitor<'tcx> { let ct = self.tcx.expand_abstract_consts(ct); match ct.kind() { - ty::ConstKind::Unevaluated(proj) if self.tcx.features().min_generic_const_args() => { + ty::ConstKind::Unevaluated( + proj @ ty::UnevaluatedConst { + kind: ty::UnevaluatedConstKind::Projection { .. }, + .. + }, + ) if self.tcx.features().min_generic_const_args() => { match self.allow_self_projections { - AllowSelfProjections::Yes - if matches!(self.tcx.def_kind(proj.def), DefKind::AssocConst { .. }) - && let trait_def_id = self.tcx.parent(proj.def) - && self.tcx.def_kind(trait_def_id) == DefKind::Trait => - { + AllowSelfProjections::Yes => { + let trait_def_id = self.tcx.parent(proj.kind.def_id()); let trait_ref = ty::TraitRef::from_assoc(self.tcx, trait_def_id, proj.args); // Only walk contained consts if the parent trait is not a supertrait. @@ -903,7 +904,7 @@ impl<'tcx> TypeVisitor> for IllegalSelfTypeVisitor<'tcx> { ct.super_visit_with(self) } } - _ => ct.super_visit_with(self), + AllowSelfProjections::No => ct.super_visit_with(self), } } _ => ct.super_visit_with(self), diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 914e103afded3..11944a80a99b4 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -560,7 +560,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { ty::ConstKind::Value(cv) => cv.ty, ty::ConstKind::Unevaluated(uv) => infcx .tcx - .type_of(uv.def) + .type_of(uv.kind.def_id()) .instantiate(infcx.tcx, uv.args) .skip_norm_wip(), // FIXME(generic_const_exprs): we should construct an alias like @@ -719,13 +719,13 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { let c2 = tcx.expand_abstract_consts(c2); debug!("equating consts:\nc1= {:?}\nc2= {:?}", c1, c2); - use rustc_hir::def::DefKind; match (c1.kind(), c2.kind()) { (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) - if a.def == b.def + if a.kind == b.kind && matches!( - tcx.def_kind(a.def), - DefKind::AssocConst { .. } + a.kind, + ty::UnevaluatedConstKind::Projection { .. } + | ty::UnevaluatedConstKind::Inherent { .. } ) => { if let Ok(new_obligations) = infcx @@ -734,8 +734,8 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { // `generic_const_exprs` .eq( DefineOpaqueTypes::Yes, - ty::AliasTerm::from_unevaluated_const(tcx, a), - ty::AliasTerm::from_unevaluated_const(tcx, b), + ty::AliasTerm::from(a), + ty::AliasTerm::from(b), ) { return ProcessResult::Changed(mk_pending( diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index a834dbd1604f8..c37b50e47129a 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -27,7 +27,6 @@ use std::fmt::Debug; use std::ops::ControlFlow; use rustc_errors::ErrorGuaranteed; -use rustc_hir::def::DefKind; pub use rustc_infer::traits::*; use rustc_macros::TypeVisitable; use rustc_middle::query::Providers; @@ -368,7 +367,7 @@ pub fn normalize_param_env_or_error<'tcx>( // const arguments that have a non-empty param env are array repeat counts. These // do not appear in the type system though. if let ty::ConstKind::Unevaluated(uv) = c.kind() - && self.0.def_kind(uv.def) == DefKind::AnonConst + && matches!(uv.kind, ty::UnevaluatedConstKind::Anon { .. }) { let infcx = self.0.infer_ctxt().build(TypingMode::non_body_analysis()); let c = evaluate_const(&infcx, c, ty::ParamEnv::empty()); @@ -607,8 +606,8 @@ pub fn try_evaluate_const<'tcx>( | ty::ConstKind::Placeholder(_) | ty::ConstKind::Expr(_) => Err(EvaluateConstErr::HasGenericsOrInfers), ty::ConstKind::Unevaluated(uv) => { - let opt_anon_const_kind = - (tcx.def_kind(uv.def) == DefKind::AnonConst).then(|| tcx.anon_const_kind(uv.def)); + let opt_anon_const_kind = matches!(uv.kind, ty::UnevaluatedConstKind::Anon { .. }) + .then(|| tcx.anon_const_kind(uv.kind.def_id())); // Postpone evaluation of constants that depend on generic parameters or // inference variables. @@ -630,7 +629,7 @@ pub fn try_evaluate_const<'tcx>( // `feature(generic_const_exprs)` causes anon consts to inherit all parent generics. This can cause // inference variables and generic parameters to show up in `ty::Const` even though the anon const // does not actually make use of them. We handle this case specially and attempt to evaluate anyway. - match tcx.thir_abstract_const(uv.def) { + match tcx.thir_abstract_const(uv.kind.def_id()) { Ok(Some(ct)) => { let ct = tcx.expand_abstract_consts( ct.instantiate(tcx, uv.args).skip_norm_wip(), @@ -651,8 +650,9 @@ pub fn try_evaluate_const<'tcx>( } } Err(_) | Ok(None) => { - let args = GenericArgs::identity_for_item(tcx, uv.def); - let typing_env = ty::TypingEnv::post_analysis(tcx, uv.def); + let args = GenericArgs::identity_for_item(tcx, uv.kind.def_id()); + let typing_env = + ty::TypingEnv::post_analysis(tcx, uv.kind.def_id()); (args, typing_env) } } @@ -680,8 +680,8 @@ pub fn try_evaluate_const<'tcx>( // affect evaluation of the constant as this would make it a "truly" generic const arg. // To prevent this we discard all the generic arguments and evalaute with identity args // and in its own environment instead of the current environment we are normalizing in. - let args = GenericArgs::identity_for_item(tcx, uv.def); - let typing_env = ty::TypingEnv::post_analysis(tcx, uv.def); + let args = GenericArgs::identity_for_item(tcx, uv.kind.def_id()); + let typing_env = ty::TypingEnv::post_analysis(tcx, uv.kind.def_id()); (args, typing_env) } @@ -716,17 +716,21 @@ pub fn try_evaluate_const<'tcx>( } }; - let uv = ty::UnevaluatedConst::new(uv.def, args); + let uv = ty::UnevaluatedConst::new(tcx, uv.kind, args); let erased_uv = tcx.erase_and_anonymize_regions(uv); use rustc_middle::mir::interpret::ErrorHandled; // FIXME: `def_span` will point at the definition of this const; ideally, we'd point at // where it gets used as a const generic. - match tcx.const_eval_resolve_for_typeck(typing_env, erased_uv, tcx.def_span(uv.def)) { + match tcx.const_eval_resolve_for_typeck( + typing_env, + erased_uv, + tcx.def_span(uv.kind.def_id()), + ) { Ok(Ok(val)) => Ok(ty::Const::new_value( tcx, val, - tcx.type_of(uv.def).instantiate(tcx, uv.args).skip_norm_wip(), + tcx.type_of(uv.kind.def_id()).instantiate(tcx, uv.args).skip_norm_wip(), )), Ok(Err(_)) => { let e = tcx.dcx().delayed_bug( diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index 84dbd53de83f2..fa2cfdab13b17 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::{ @@ -450,7 +449,7 @@ impl<'a, 'b, 'tcx> TypeFolder> for AssocTypeNormalizer<'a, 'b, 'tcx if tcx.features().generic_const_exprs() // Normalize type_const items even with feature `generic_const_exprs`. - && !matches!(ct.kind(), ty::ConstKind::Unevaluated(uv) if tcx.is_type_const(uv.def)) + && !matches!(ct.kind(), ty::ConstKind::Unevaluated(uv) if tcx.is_type_const(uv.kind.def_id())) || !needs_normalization(self.selcx.infcx, &ct) { return ct; @@ -461,30 +460,24 @@ 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, + // Note that the Projection/Inherent/Free 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 ct = match uv.kind { + ty::UnevaluatedConstKind::Projection { .. } => { + self.normalize_trait_projection(uv.into()).expect_const() + } + ty::UnevaluatedConstKind::Inherent { .. } => { + self.normalize_inherent_projection(uv.into()).expect_const() + } + ty::UnevaluatedConstKind::Free { .. } => { + self.normalize_free_alias(uv.into()).expect_const() + } + ty::UnevaluatedConstKind::Anon { .. } => { let ct = ct.super_fold_with(self); super::with_replaced_escaping_bound_vars( self.selcx.infcx, @@ -493,9 +486,6 @@ impl<'a, 'b, 'tcx> TypeFolder> for AssocTypeNormalizer<'a, 'b, 'tcx |ct| super::evaluate_const(self.selcx.infcx, ct, self.param_env), ) } - kind => { - unreachable!("unexpected `DefKind` for const alias to resolve to: {:?}", kind) - } }; // We re-fold the normalized const as the `ty` field on `ConstKind::Value` may be diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 900d55cc556fc..46c1c8e60a329 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -469,7 +469,7 @@ fn normalize_to_error<'a, 'tcx>( | ty::AliasTermKind::FreeTy { .. } => selcx.infcx.next_ty_var(cause.span).into(), ty::AliasTermKind::FreeConst { .. } | ty::AliasTermKind::InherentConst { .. } - | ty::AliasTermKind::UnevaluatedConst { .. } + | ty::AliasTermKind::AnonConst { .. } | ty::AliasTermKind::ProjectionConst { .. } => { selcx.infcx.next_const_var(cause.span).into() } diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index e8c5d10c78ce3..5b1f2e3a267a9 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,16 @@ 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 constant = match uv.kind { + ty::UnevaluatedConstKind::Anon { .. } => { + 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(uv.into())?.expect_const(), }; debug!(?constant, ?self.param_env); constant.try_super_fold_with(self) @@ -338,8 +337,7 @@ impl<'a, 'tcx> QueryNormalizer<'a, 'tcx> { ty::AliasTermKind::InherentTy { .. } | ty::AliasTermKind::InherentConst { .. } => { tcx.normalize_canonicalized_inherent_projection(c_term) } - kind @ (ty::AliasTermKind::OpaqueTy { .. } - | ty::AliasTermKind::UnevaluatedConst { .. }) => { + kind @ (ty::AliasTermKind::OpaqueTy { .. } | ty::AliasTermKind::AnonConst { .. }) => { unreachable!("did not expect {kind:?} due to match arm above") } }?; diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index eadc937639f20..6900024f198b8 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -881,13 +881,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { c1, c2 ); - use rustc_hir::def::DefKind; match (c1.kind(), c2.kind()) { (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) - if a.def == b.def + if a.kind == b.kind && matches!( - tcx.def_kind(a.def), - DefKind::AssocConst { .. } + a.kind, + ty::UnevaluatedConstKind::Projection { .. } + | ty::UnevaluatedConstKind::Inherent { .. } ) => { if let Ok(InferOk { obligations, value: () }) = self @@ -897,8 +897,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // `generic_const_exprs` .eq( DefineOpaqueTypes::Yes, - ty::AliasTerm::from_unevaluated_const(tcx, a), - ty::AliasTerm::from_unevaluated_const(tcx, b), + ty::AliasTerm::from(a), + ty::AliasTerm::from(b), ) { return self.evaluate_predicates_recursively( @@ -989,7 +989,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::ConstKind::Value(cv) => cv.ty, ty::ConstKind::Unevaluated(uv) => self .tcx() - .type_of(uv.def) + .type_of(uv.kind.def_id()) .instantiate(self.tcx(), uv.args) .skip_norm_wip(), // FIXME(generic_const_exprs): See comment in `fulfill.rs` diff --git a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs index fe00e9b4f8426..03edfeb06d8c4 100644 --- a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs @@ -41,7 +41,7 @@ impl<'tcx> At<'_, 'tcx> { if self.infcx.next_trait_solver() { let term = term.skip_normalization(); - if let None = term.to_alias_term(self.infcx.tcx) { + if let None = term.to_alias_term() { return Ok(term); } diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index fdf32d32e9058..a2143a7462a84 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; @@ -1065,7 +1064,8 @@ impl<'a, 'tcx> TypeVisitor> for WfPredicates<'a, 'tcx> { ty::ConstKind::Unevaluated(uv) => { if !c.has_escaping_bound_vars() { // Skip type consts as mGCA doesn't support evaluatable clauses - if !tcx.is_type_const(uv.def) && !tcx.features().generic_const_args() { + if !tcx.is_type_const(uv.kind.def_id()) && !tcx.features().generic_const_args() + { let predicate = ty::Binder::dummy(ty::PredicateKind::Clause( ty::ClauseKind::ConstEvaluatable(c), )); @@ -1079,15 +1079,11 @@ 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), - ); + if matches!(uv.kind, ty::UnevaluatedConstKind::Inherent { .. }) { + self.add_wf_preds_for_inherent_projection(uv.into()); return; // Subtree is handled by above function } else { - let obligations = self.nominal_obligations(uv.def, uv.args); + let obligations = self.nominal_obligations(uv.kind.def_id(), uv.args); self.out.extend(obligations); } } diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs index 24415c5a50e97..b459582fdbe56 100644 --- a/compiler/rustc_ty_utils/src/consts.rs +++ b/compiler/rustc_ty_utils/src/consts.rs @@ -70,7 +70,11 @@ fn recurse_build<'tcx>( } &ExprKind::ZstLiteral { user_ty: _ } => ty::Const::zero_sized(tcx, node.ty), &ExprKind::NamedConst { def_id, args, user_ty: _ } => { - let uneval = ty::UnevaluatedConst::new(def_id, args); + let uneval = ty::UnevaluatedConst::new( + tcx, + ty::UnevaluatedConstKind::new_from_def_id(tcx, def_id), + args, + ); ty::Const::new_unevaluated(tcx, uneval) } ExprKind::ConstParam { param, .. } => ty::Const::new_param(tcx, *param), diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs index 4017aab7a6b57..0a13dd5e173a6 100644 --- a/compiler/rustc_type_ir/src/const_kind.rs +++ b/compiler/rustc_type_ir/src/const_kind.rs @@ -75,16 +75,63 @@ impl fmt::Debug for ConstKind { derive(Decodable_NoContext, Encodable_NoContext, StableHash_NoContext) )] pub struct UnevaluatedConst { - pub def: I::UnevaluatedConstId, + #[type_foldable(identity)] + #[type_visitable(ignore)] + pub kind: UnevaluatedConstKind, pub args: I::GenericArgs, + + /// This field exists to prevent the creation of `UnevaluatedConst` without using [`UnevaluatedConst::new`]. + #[derive_where(skip(Debug))] + pub(crate) _use_unevaluated_const_new_instead: (), } impl Eq for UnevaluatedConst {} impl UnevaluatedConst { #[inline] - pub fn new(def: I::UnevaluatedConstId, args: I::GenericArgs) -> UnevaluatedConst { - UnevaluatedConst { def, args } + pub fn new( + interner: I, + kind: UnevaluatedConstKind, + args: I::GenericArgs, + ) -> UnevaluatedConst { + interner.debug_assert_args_compatible(kind.def_id(), args); + UnevaluatedConst { kind, args, _use_unevaluated_const_new_instead: () } + } +} + +/// UnevaluatedConstKind is extremely similar to AliasTyKind, and likely should be reasoned about +/// and handled in very similar ways. The documentation for AliasTyKind/etc. may be helpful when +/// learning about UnevaluatedConstKind. +#[derive_where(Clone, Copy, Hash, PartialEq, Debug; I: Interner)] +#[derive(GenericTypeVisitable, Lift_Generic)] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, Decodable_NoContext, StableHash_NoContext) +)] +pub enum UnevaluatedConstKind { + /// A projection `::AssocConst` + Projection { def_id: I::TraitAssocConstId }, + /// An associated constant in an inherent `impl` + Inherent { def_id: I::InherentAssocConstId }, + /// A free constant, outside an impl block. + Free { def_id: I::FreeConstAliasId }, + /// Anonymous constant, e.g. the `1 + 2` in `[u8; 1 + 2]`. + Anon { def_id: I::UnevaluatedConstId }, +} + +impl UnevaluatedConstKind { + pub fn new_from_def_id(interner: I, def_id: I::DefId) -> Self { + interner.unevaluated_const_kind_from_def_id(def_id) + } + + pub fn def_id(self) -> I::DefId { + match self { + UnevaluatedConstKind::Projection { def_id } => def_id.into(), + UnevaluatedConstKind::Inherent { def_id } => def_id.into(), + UnevaluatedConstKind::Free { def_id } => def_id.into(), + UnevaluatedConstKind::Anon { def_id } => def_id.into(), + //UnevaluatedConstKind::Expr { def_id } => def_id.into(), + } } } diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index 8859ab7c037b0..e0fe608198921 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -400,16 +400,14 @@ pub trait Term>: } } - fn to_alias_term(self, interner: I) -> Option> { + fn to_alias_term(self) -> Option> { match self.kind() { ty::TermKind::Ty(ty) => match ty.kind() { ty::Alias(alias_ty) => Some(alias_ty.into()), _ => None, }, ty::TermKind::Const(ct) => match ct.kind() { - ty::ConstKind::Unevaluated(uv) => { - Some(ty::AliasTerm::from_unevaluated_const(interner, uv)) - } + ty::ConstKind::Unevaluated(uv) => Some(uv.into()), _ => None, }, } diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 09def0212a153..a4737cf137b0c 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -244,6 +244,11 @@ pub trait Interner: fn alias_ty_kind_from_def_id(self, def_id: Self::DefId) -> ty::AliasTyKind; + fn unevaluated_const_kind_from_def_id( + self, + def_id: Self::DefId, + ) -> ty::UnevaluatedConstKind; + // FIXME: remove in favor of explicit construction fn alias_term_kind_from_def_id(self, def_id: Self::DefId) -> ty::AliasTermKind; diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs index 301cf7dbf1087..e6b58fe078b48 100644 --- a/compiler/rustc_type_ir/src/predicate.rs +++ b/compiler/rustc_type_ir/src/predicate.rs @@ -12,7 +12,7 @@ use crate::inherent::*; use crate::lift::Lift; use crate::upcast::{Upcast, UpcastFrom}; use crate::visit::TypeVisitableExt as _; -use crate::{self as ty, AliasTyKind, Interner}; +use crate::{self as ty, AliasTyKind, Interner, UnevaluatedConstKind}; /// `A: 'region` #[derive_where(Clone, Hash, PartialEq, Debug; I: Interner, A)] @@ -594,7 +594,7 @@ pub enum AliasTermKind { FreeTy { def_id: I::FreeTyAliasId }, /// An unevaluated anonymous constants. - UnevaluatedConst { def_id: I::UnevaluatedConstId }, + AnonConst { def_id: I::UnevaluatedConstId }, /// An unevaluated const coming from an associated const. ProjectionConst { def_id: I::TraitAssocConstId }, /// A top level const item not part of a trait or impl. @@ -613,7 +613,7 @@ impl AliasTermKind { AliasTermKind::OpaqueTy { .. } => "opaque type", AliasTermKind::FreeTy { .. } => "type alias", AliasTermKind::FreeConst { .. } => "unevaluated constant", - AliasTermKind::UnevaluatedConst { .. } => "unevaluated constant", + AliasTermKind::AnonConst { .. } => "unevaluated constant", } } @@ -624,7 +624,7 @@ impl AliasTermKind { | AliasTermKind::OpaqueTy { .. } | AliasTermKind::FreeTy { .. } => true, - AliasTermKind::UnevaluatedConst { .. } + AliasTermKind::AnonConst { .. } | AliasTermKind::ProjectionConst { .. } | AliasTermKind::InherentConst { .. } | AliasTermKind::FreeConst { .. } => false, @@ -638,7 +638,7 @@ impl AliasTermKind { AliasTermKind::InherentTy { def_id } => def_id.into(), AliasTermKind::OpaqueTy { def_id } => def_id.into(), AliasTermKind::FreeTy { def_id } => def_id.into(), - AliasTermKind::UnevaluatedConst { def_id } => def_id.into(), + AliasTermKind::AnonConst { def_id } => def_id.into(), AliasTermKind::ProjectionConst { def_id } => def_id.into(), AliasTermKind::FreeConst { def_id } => def_id.into(), AliasTermKind::InherentConst { def_id } => def_id.into(), @@ -657,6 +657,21 @@ impl From> for AliasTermKind { } } +impl From> for AliasTermKind { + fn from(value: ty::UnevaluatedConstKind) -> Self { + match value { + ty::UnevaluatedConstKind::Projection { def_id } => { + AliasTermKind::ProjectionConst { def_id } + } + ty::UnevaluatedConstKind::Inherent { def_id } => { + AliasTermKind::InherentConst { def_id } + } + ty::UnevaluatedConstKind::Free { def_id } => AliasTermKind::FreeConst { def_id }, + ty::UnevaluatedConstKind::Anon { def_id } => AliasTermKind::AnonConst { def_id }, + } + } +} + /// Represents the unprojected term of a projection goal. /// /// * For a projection, this would be `>::N<...>`. @@ -716,11 +731,6 @@ impl AliasTerm { Self::new_from_args(interner, kind, args) } - pub fn from_unevaluated_const(interner: I, ct: ty::UnevaluatedConst) -> Self { - let kind = interner.alias_term_kind_from_def_id(ct.def.into()); - AliasTerm::new_from_args(interner, kind, ct.args) - } - pub fn expect_ty(self, interner: I) -> ty::AliasTy { let kind = match self.kind(interner) { AliasTermKind::ProjectionTy { def_id } => AliasTyKind::Projection { def_id }, @@ -729,7 +739,7 @@ impl AliasTerm { AliasTermKind::FreeTy { def_id } => AliasTyKind::Free { def_id }, kind @ (AliasTermKind::InherentConst { .. } | AliasTermKind::FreeConst { .. } - | AliasTermKind::UnevaluatedConst { .. } + | AliasTermKind::AnonConst { .. } | AliasTermKind::ProjectionConst { .. }) => { panic!("Cannot turn `{}` into `AliasTy`", kind.descr()) } @@ -739,10 +749,12 @@ impl AliasTerm { pub fn expect_ct(self, interner: I) -> ty::UnevaluatedConst { let def = match self.kind(interner) { - AliasTermKind::InherentConst { def_id } => def_id.into(), - AliasTermKind::FreeConst { def_id } => def_id.into(), - AliasTermKind::UnevaluatedConst { def_id } => def_id, - AliasTermKind::ProjectionConst { def_id } => def_id.into(), + AliasTermKind::InherentConst { def_id } => UnevaluatedConstKind::Inherent { def_id }, + AliasTermKind::FreeConst { def_id } => UnevaluatedConstKind::Free { def_id }, + AliasTermKind::AnonConst { def_id } => UnevaluatedConstKind::Anon { def_id }, + AliasTermKind::ProjectionConst { def_id } => { + UnevaluatedConstKind::Projection { def_id } + } kind @ (AliasTermKind::ProjectionTy { .. } | AliasTermKind::InherentTy { .. } | AliasTermKind::OpaqueTy { .. } @@ -750,7 +762,7 @@ impl AliasTerm { panic!("Cannot turn `{}` into `UnevaluatedConst`", kind.descr()) } }; - ty::UnevaluatedConst { def, args: self.args } + ty::UnevaluatedConst::new(interner, def, self.args) } // FIXME: remove this function (access the field instead) @@ -764,23 +776,34 @@ impl AliasTerm { } pub fn to_term(self, interner: I) -> I::Term { - let unevaluated_const = |def_id| { - I::Const::new_unevaluated(interner, ty::UnevaluatedConst::new(def_id, self.args)).into() - }; - let alias_ty_kind = match self.kind(interner) { - AliasTermKind::FreeConst { def_id } => return unevaluated_const(def_id.into()), - AliasTermKind::InherentConst { def_id } => return unevaluated_const(def_id.into()), - AliasTermKind::UnevaluatedConst { def_id } => return unevaluated_const(def_id), - AliasTermKind::ProjectionConst { def_id } => return unevaluated_const(def_id.into()), - - AliasTermKind::ProjectionTy { def_id } => ty::Projection { def_id }, - AliasTermKind::InherentTy { def_id } => ty::Inherent { def_id }, - AliasTermKind::OpaqueTy { def_id } => ty::Opaque { def_id }, - AliasTermKind::FreeTy { def_id } => ty::Free { def_id }, + let alias_ty = |kind| { + Ty::new_alias(interner, ty::AliasTy::new_from_args(interner, kind, self.args)).into() }; - - Ty::new_alias(interner, ty::AliasTy::new_from_args(interner, alias_ty_kind, self.args)) + let unevaluated_const = |kind| { + I::Const::new_unevaluated( + interner, + ty::UnevaluatedConst::new(interner, kind, self.args), + ) .into() + }; + match self.kind(interner) { + AliasTermKind::FreeConst { def_id } => { + unevaluated_const(UnevaluatedConstKind::Free { def_id }) + } + AliasTermKind::InherentConst { def_id } => { + unevaluated_const(UnevaluatedConstKind::Inherent { def_id }) + } + AliasTermKind::AnonConst { def_id } => { + unevaluated_const(UnevaluatedConstKind::Anon { def_id }) + } + AliasTermKind::ProjectionConst { def_id } => { + unevaluated_const(UnevaluatedConstKind::Projection { def_id }) + } + AliasTermKind::ProjectionTy { def_id } => alias_ty(ty::Projection { def_id }), + AliasTermKind::InherentTy { def_id } => alias_ty(ty::Inherent { def_id }), + AliasTermKind::OpaqueTy { def_id } => alias_ty(ty::Opaque { def_id }), + AliasTermKind::FreeTy { def_id } => alias_ty(ty::Free { def_id }), + } } pub fn with_args(self, interner: I, args: I::GenericArgs) -> Self { @@ -809,7 +832,7 @@ impl AliasTerm { AliasTermKind::InherentTy { .. } | AliasTermKind::OpaqueTy { .. } | AliasTermKind::FreeTy { .. } - | AliasTermKind::UnevaluatedConst { .. } + | AliasTermKind::AnonConst { .. } | AliasTermKind::FreeConst { .. } | AliasTermKind::InherentConst { .. } => None, } @@ -885,6 +908,16 @@ impl From> for AliasTerm { } } +impl From> for AliasTerm { + fn from(ty: ty::UnevaluatedConst) -> Self { + AliasTerm { + args: ty.args, + kind: AliasTermKind::from(ty.kind), + _use_alias_term_new_instead: (), + } + } +} + /// This kind of predicate has no *direct* correspondent in the /// syntax, but it roughly corresponds to the syntactic forms: /// diff --git a/compiler/rustc_type_ir/src/relate.rs b/compiler/rustc_type_ir/src/relate.rs index 51de99e92fcad..d1c9a5c8fd903 100644 --- a/compiler/rustc_type_ir/src/relate.rs +++ b/compiler/rustc_type_ir/src/relate.rs @@ -251,7 +251,7 @@ impl Relate for ty::AliasTerm { | ty::AliasTermKind::FreeTy { .. } | ty::AliasTermKind::InherentTy { .. } | ty::AliasTermKind::InherentConst { .. } - | ty::AliasTermKind::UnevaluatedConst { .. } + | ty::AliasTermKind::AnonConst { .. } | ty::AliasTermKind::ProjectionConst { .. } => { relate_args_invariantly(relation, a.args, b.args)? } @@ -591,11 +591,11 @@ pub fn structurally_relate_consts>( // While this is slightly incorrect, it shouldn't matter for `min_const_generics` // and is the better alternative to waiting until `generic_const_exprs` can // be stabilized. - (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) if au.def == bu.def => { + (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) if au.kind == bu.kind => { // FIXME(mgca): remove this if cfg!(debug_assertions) { - let a_ty = cx.type_of(au.def.into()).instantiate(cx, au.args).skip_norm_wip(); - let b_ty = cx.type_of(bu.def.into()).instantiate(cx, bu.args).skip_norm_wip(); + let a_ty = cx.type_of(au.kind.def_id()).instantiate(cx, au.args).skip_norm_wip(); + let b_ty = cx.type_of(bu.kind.def_id()).instantiate(cx, bu.args).skip_norm_wip(); assert_eq!(a_ty, b_ty); } @@ -605,7 +605,7 @@ pub fn structurally_relate_consts>( au.args, bu.args, )?; - return Ok(Const::new_unevaluated(cx, ty::UnevaluatedConst { def: au.def, args })); + return Ok(Const::new_unevaluated(cx, ty::UnevaluatedConst::new(cx, au.kind, args))); } (ty::ConstKind::Expr(ae), ty::ConstKind::Expr(be)) => { let expr = relation.relate(ae, be)?; diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 253d4dcf9f2a5..4367209f6f74d 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -350,13 +350,13 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol { pub(crate) fn print_const(tcx: TyCtxt<'_>, n: ty::Const<'_>) -> String { match n.kind() { - ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args: _ }) => { - if let Some(def) = def.as_local() + ty::ConstKind::Unevaluated(ty::UnevaluatedConst { kind, .. }) => { + if let Some(def) = kind.def_id().as_local() && let Some(body_id) = tcx.hir_maybe_body_owned_by(def) { rendered_const(tcx, body_id, def) } else { - inline::print_inlined_const(tcx, def) + inline::print_inlined_const(tcx, kind.def_id()) } } // array lengths are obviously usize diff --git a/tests/mir-opt/issue_99325.main.built.after.32bit.mir b/tests/mir-opt/issue_99325.main.built.after.32bit.mir index 9e48cf038bf2c..4d4e858bed630 100644 --- a/tests/mir-opt/issue_99325.main.built.after.32bit.mir +++ b/tests/mir-opt/issue_99325.main.built.after.32bit.mir @@ -2,7 +2,7 @@ | User Type Annotations | 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [&*b"AAAA"], user_self_ty: None }), max_universe: U0, var_kinds: [] }, span: $DIR/issue_99325.rs:13:16: 13:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} -| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [UnevaluatedConst { def: DefId(0:8 ~ issue_99325[d56d]::main::{constant#1}), args: [] }], user_self_ty: None }), max_universe: U0, var_kinds: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} +| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [UnevaluatedConst { kind: Anon { def_id: DefId(0:8 ~ issue_99325[d56d]::main::{constant#1}) }, args: [], .. }], user_self_ty: None }), max_universe: U0, var_kinds: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} | fn main() -> () { let mut _0: (); diff --git a/tests/mir-opt/issue_99325.main.built.after.64bit.mir b/tests/mir-opt/issue_99325.main.built.after.64bit.mir index 9e48cf038bf2c..4d4e858bed630 100644 --- a/tests/mir-opt/issue_99325.main.built.after.64bit.mir +++ b/tests/mir-opt/issue_99325.main.built.after.64bit.mir @@ -2,7 +2,7 @@ | User Type Annotations | 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [&*b"AAAA"], user_self_ty: None }), max_universe: U0, var_kinds: [] }, span: $DIR/issue_99325.rs:13:16: 13:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} -| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [UnevaluatedConst { def: DefId(0:8 ~ issue_99325[d56d]::main::{constant#1}), args: [] }], user_self_ty: None }), max_universe: U0, var_kinds: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} +| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [UnevaluatedConst { kind: Anon { def_id: DefId(0:8 ~ issue_99325[d56d]::main::{constant#1}) }, args: [], .. }], user_self_ty: None }), max_universe: U0, var_kinds: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} | fn main() -> () { let mut _0: (); diff --git a/tests/ui/offset-of/inside-array-length.stderr b/tests/ui/offset-of/inside-array-length.stderr index de110939d4aad..2d2ba8711de7c 100644 --- a/tests/ui/offset-of/inside-array-length.stderr +++ b/tests/ui/offset-of/inside-array-length.stderr @@ -53,7 +53,7 @@ note: ...which requires borrow-checking `foo::{constant#0}`... | LL | fn foo<'a, T: 'a>(_: [(); std::mem::offset_of!((T,), 0)]) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires normalizing `Binder { value: ConstEvaluatable(UnevaluatedConst { def: DefId(0:7 ~ inside_array_length[07d6]::foo::{constant#0}), args: ['^c_1, T/#1] }), bound_vars: [] }`... +note: ...which requires normalizing `Binder { value: ConstEvaluatable(UnevaluatedConst { kind: Anon { def_id: DefId(0:7 ~ inside_array_length[07d6]::foo::{constant#0}) }, args: ['^c_1, T/#1], .. }), bound_vars: [] }`... --> $DIR/inside-array-length.rs:9:27 | LL | fn foo<'a, T: 'a>(_: [(); std::mem::offset_of!((T,), 0)]) {}