From 5070cbaf21382275053b1bb3f3948d0170c94ca6 Mon Sep 17 00:00:00 2001 From: khyperia <953151+khyperia@users.noreply.github.com> Date: Wed, 3 Jun 2026 12:13:15 +0200 Subject: [PATCH] remove UnevaluatedConstKind::def_id --- compiler/rustc_borrowck/src/type_check/mod.rs | 13 ++-- .../rustc_hir_analysis/src/check/check.rs | 6 +- .../rustc_hir_analysis/src/check/wfcheck.rs | 6 +- .../src/collect/predicates_of.rs | 20 ++++-- .../rustc_middle/src/mir/interpret/queries.rs | 17 +++-- compiler/rustc_middle/src/mir/pretty.rs | 14 ++-- .../rustc_middle/src/ty/abstract_const.rs | 4 +- .../src/ty/context/impl_interner.rs | 4 ++ .../src/thir/pattern/const_to_pat.rs | 2 +- .../rustc_next_trait_solver/src/solve/mod.rs | 4 +- .../src/unstable/convert/stable/ty.rs | 16 +++-- compiler/rustc_symbol_mangling/src/v0.rs | 11 +++- .../traits/fulfillment_errors.rs | 65 +++++++++---------- .../src/solve/fulfill/derive_errors.rs | 6 +- .../src/traits/auto_trait.rs | 8 +-- .../src/traits/const_evaluatable.rs | 2 +- .../src/traits/dyn_compatibility.rs | 15 ++--- .../src/traits/fulfill.rs | 6 +- .../rustc_trait_selection/src/traits/mod.rs | 42 ++++++------ .../src/traits/normalize.rs | 2 +- .../src/traits/select/mod.rs | 6 +- .../rustc_trait_selection/src/traits/wf.rs | 20 +++--- compiler/rustc_type_ir/src/const_kind.rs | 48 ++++++++++++-- compiler/rustc_type_ir/src/interner.rs | 2 + compiler/rustc_type_ir/src/relate.rs | 42 +++++++----- src/librustdoc/clean/utils.rs | 21 +++--- 26 files changed, 236 insertions(+), 166 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index b1cf7546878ab..450ac46aab521 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1760,11 +1760,14 @@ 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.kind.def_id(), - args: uv.args, - promoted: None, - }), + ty::ConstKind::Unevaluated(uv) => match uv.kind { + ty::UnevaluatedConstKind::Projection { def_id } + | ty::UnevaluatedConstKind::Inherent { def_id } + | ty::UnevaluatedConstKind::Free { def_id } + | ty::UnevaluatedConstKind::Anon { def_id } => { + Some(UnevaluatedConst { def: def_id, args: uv.args, promoted: None }) + } + }, _ => None, }, Const::Unevaluated(uv, _) => Some(uv), diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 14759ad919e24..8ed8cd140e307 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -775,8 +775,10 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), if has_default { // 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.kind.def_id()); + if let ty::ConstKind::Unevaluated(uv) = ct.kind() + && let Some(def_id) = uv.kind.opt_def_id() + { + tcx.ensure_ok().type_of(def_id); } } } diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index f495df360e6d9..408d119e5565d 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1535,11 +1535,7 @@ 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.kind.def_id()) - .instantiate(infcx.tcx, uv.args) - .skip_norm_wip(), + ty::ConstKind::Unevaluated(uv) => uv.type_of(infcx.tcx).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 cf29a76418792..8abdb3497b46a 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -419,8 +419,16 @@ fn const_evaluatable_predicates_of<'tcx>( preds: FxIndexSet<(ty::Clause<'tcx>, Span)>, } - fn is_const_param_default(tcx: TyCtxt<'_>, def: LocalDefId) -> bool { - let hir_id = tcx.local_def_id_to_hir_id(def); + fn is_const_param_default(tcx: TyCtxt<'_>, kind: ty::UnevaluatedConstKind<'_>) -> bool { + let def_id = match kind { + ty::UnevaluatedConstKind::Projection { def_id } => def_id, + ty::UnevaluatedConstKind::Inherent { def_id } => def_id, + ty::UnevaluatedConstKind::Free { def_id } => def_id, + ty::UnevaluatedConstKind::Anon { def_id } => def_id, + }; + let Some(local) = def_id.as_local() else { return false }; + + let hir_id = tcx.local_def_id_to_hir_id(local); let (_, parent_node) = tcx .hir_parent_iter(hir_id) .skip_while(|(_, n)| matches!(n, Node::ConstArg(..))) @@ -435,9 +443,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.kind.def_id().as_local() - && is_const_param_default(self.tcx, local) - { + if is_const_param_default(self.tcx, uv.kind) { // Do not look into const param defaults, // these get checked when they are actually instantiated. // @@ -449,11 +455,11 @@ fn const_evaluatable_predicates_of<'tcx>( } // Skip type consts as mGCA doesn't support evaluatable clauses. - if self.tcx.is_type_const(uv.kind.def_id()) { + if uv.kind.is_type_const(self.tcx) { return; } - let span = self.tcx.def_span(uv.kind.def_id()); + let span = uv.kind.def_span(self.tcx); self.preds.insert((ty::ClauseKind::ConstEvaluatable(c).upcast(self.tcx), span)); } } diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs index 80275b58b96dd..55b440434be02 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs @@ -103,7 +103,14 @@ impl<'tcx> TyCtxt<'tcx> { bug!("did not expect inference variables here"); } - let cid = match ty::Instance::try_resolve(self, typing_env, ct.kind.def_id(), ct.args) { + let def_id = match ct.kind { + ty::UnevaluatedConstKind::Projection { def_id } + | ty::UnevaluatedConstKind::Inherent { def_id } + | ty::UnevaluatedConstKind::Free { def_id } + | ty::UnevaluatedConstKind::Anon { def_id } => def_id, + }; + + let cid = match ty::Instance::try_resolve(self, typing_env, 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. @@ -136,12 +143,14 @@ impl<'tcx> TyCtxt<'tcx> { && !self.is_trivial_const(cid.instance.def_id()) { let mir_body = self.mir_for_ctfe(cid.instance.def_id()); - if mir_body.is_polymorphic { - let Some(local_def_id) = ct.kind.def_id().as_local() else { return }; + if mir_body.is_polymorphic + && let Some(def_id) = ct.kind.opt_def_id() + && let Some(local_def_id) = def_id.as_local() + { self.emit_node_span_lint( lint::builtin::CONST_EVALUATABLE_UNCHECKED, self.local_def_id_to_hir_id(local_def_id), - self.def_span(ct.kind.def_id()), + self.def_span(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 7f8f7293596aa..942c36f343343 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -1492,11 +1492,15 @@ 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.kind.def_id()), - uv.args, - ) + let kind = match uv.kind { + ty::UnevaluatedConstKind::Projection { def_id } + | ty::UnevaluatedConstKind::Inherent { def_id } + | ty::UnevaluatedConstKind::Free { def_id } + | ty::UnevaluatedConstKind::Anon { def_id } => { + self.tcx.def_path_str(def_id) + } + }; + format!("ty::Unevaluated({}, {:?})", kind, 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 984c9ec48321d..ac38053d153cc 100644 --- a/compiler/rustc_middle/src/ty/abstract_const.rs +++ b/compiler/rustc_middle/src/ty/abstract_const.rs @@ -52,8 +52,8 @@ 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.kind.def_id()) { + ty::ConstKind::Unevaluated(uv) if let Some(def_id) = uv.kind.opt_def_id() => { + match self.tcx.thir_abstract_const(def_id) { Err(e) => ty::Const::new_error(self.tcx, e), Ok(Some(bac)) => { let args = self.tcx.erase_and_anonymize_regions(uv.args); diff --git a/compiler/rustc_middle/src/ty/context/impl_interner.rs b/compiler/rustc_middle/src/ty/context/impl_interner.rs index bc8b83e460080..63ad2ebe7899d 100644 --- a/compiler/rustc_middle/src/ty/context/impl_interner.rs +++ b/compiler/rustc_middle/src/ty/context/impl_interner.rs @@ -199,6 +199,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.anon_const_kind(def_id) } + fn def_span(self, def_id: DefId) -> Span { + self.def_span(def_id) + } + type AdtDef = ty::AdtDef<'tcx>; fn adt_def(self, adt_def_id: DefId) -> Self::AdtDef { self.adt_def(adt_def_id) 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 1c250c58dcb97..56aeabe83898f 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 @@ -184,7 +184,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.kind.def_id()); + thir_pat.extra.get_or_insert_default().expanded_const = uv.kind.opt_def_id(); thir_pat } diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs index c27597c324271..02a90f2b5448e 100644 --- a/compiler/rustc_next_trait_solver/src/solve/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs @@ -246,9 +246,7 @@ where .evaluate_added_goals_and_make_canonical_response(Certainty::Yes) .map_err(Into::into); } - ty::ConstKind::Unevaluated(uv) => { - self.cx().type_of(uv.kind.def_id()).instantiate(self.cx(), uv.args).skip_norm_wip() - } + ty::ConstKind::Unevaluated(uv) => uv.type_of(self.cx()).skip_norm_wip(), ty::ConstKind::Expr(_) => unimplemented!( "`feature(generic_const_exprs)` is not supported in the new trait solver" ), diff --git a/compiler/rustc_public/src/unstable/convert/stable/ty.rs b/compiler/rustc_public/src/unstable/convert/stable/ty.rs index 925d4a5b40b20..e93b9ad0327ec 100644 --- a/compiler/rustc_public/src/unstable/convert/stable/ty.rs +++ b/compiler/rustc_public/src/unstable/convert/stable/ty.rs @@ -540,10 +540,18 @@ 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.kind.def_id()), - uv.args.stable(tables, cx), - ), + ty::ConstKind::Unevaluated(uv) => { + let Some(def_id) = uv.kind.opt_def_id() else { + // FIXME: implement (both AliasTy and UnevaluatedConst will be needing this soon) + panic!( + "non-defid unevaluated constants are not supported by rustc_public at the moment" + ) + }; + crate::ty::TyConstKind::Unevaluated( + tables.const_def(def_id), + uv.args.stable(tables, cx), + ) + } ty::ConstKind::Error(_) => unreachable!(), ty::ConstKind::Infer(_) => unreachable!(), ty::ConstKind::Bound(_, _) => unimplemented!(), diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index e68e76dc937d1..c6624a7820559 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -692,9 +692,14 @@ 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 { kind, args, .. }) => { - return self.print_def_path(kind.def_id(), 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 } + | ty::UnevaluatedConstKind::Anon { def_id } => { + return self.print_def_path(def_id, args); + } + }, ty::ConstKind::Expr(_) | ty::ConstKind::Infer(_) 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 f78bc3e8b4884..32b4d4948f761 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 @@ -3745,44 +3745,39 @@ 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.kind.def_id()); - let const_ty = self - .tcx - .type_of(uv.kind.def_id()) - .instantiate(self.tcx, uv.args) - .skip_norm_wip(); + let const_ty = uv.type_of(self.tcx).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) { - Ok(snippet) => { - let code = format!("[(); {snippet}{cast}]:"); - let def_id = if let ObligationCauseCode::CompareImplItem { - trait_item_def_id, - .. - } = obligation.cause.code() - { - trait_item_def_id.as_local() - } else { - Some(obligation.cause.body_id) - }; - if let Some(def_id) = def_id - && let Some(generics) = self.tcx.hir_get_generics(def_id) - { - err.span_suggestion_verbose( - generics.tail_span_for_predicate_suggestion(), - msg, - format!("{} {code}", generics.add_where_or_trailing_comma()), - Applicability::MaybeIncorrect, - ); - } else { - err.help(format!("{msg}: where {code}")); - }; - } - _ => { - err.help(msg); - } - }; + if let Some(def_id) = uv.kind.opt_def_id() + && let const_span = self.tcx.def_span(def_id) + && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(const_span) + { + let code = format!("[(); {snippet}{cast}]:"); + let suggestion_def_id = if let ObligationCauseCode::CompareImplItem { + trait_item_def_id, + .. + } = obligation.cause.code() + { + trait_item_def_id.as_local() + } else { + Some(obligation.cause.body_id) + }; + if let Some(suggestion_def_id) = suggestion_def_id + && let Some(generics) = self.tcx.hir_get_generics(suggestion_def_id) + { + err.span_suggestion_verbose( + generics.tail_span_for_predicate_suggestion(), + msg, + format!("{} {code}", generics.add_where_or_trailing_comma()), + Applicability::MaybeIncorrect, + ); + } else { + err.help(format!("{msg}: where {code}")); + }; + } else { + err.help(msg); + } Ok(err) } ty::ConstKind::Expr(_) => { 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 1ba0bb5f776ba..0ce4e9e71fc9f 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs @@ -34,11 +34,7 @@ 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.kind.def_id()) - .instantiate(infcx.tcx, uv.args) - .skip_norm_wip(), + ty::ConstKind::Unevaluated(uv) => uv.type_of(infcx.tcx).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 e080687ad4b56..3a58dbaf1ec8d 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -773,10 +773,10 @@ impl<'tcx> AutoTraitFinder<'tcx> { super::try_evaluate_const(selcx.infcx, c, obligation.param_env); if let Err(EvaluateConstErr::InvalidConstParamTy(_)) = ct { - self.tcx.dcx().emit_err(UnableToConstructConstantValue { - span: self.tcx.def_span(unevaluated.kind.def_id()), - unevaluated, - }); + let span = unevaluated.kind.def_span(self.tcx); + self.tcx + .dcx() + .emit_err(UnableToConstructConstantValue { span, unevaluated }); } ct diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 90e795f1391a4..cd9acde9d7b99 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -117,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.kind.def_id()) } else { span }, + if span == DUMMY_SP { uv.kind.def_span(tcx) } 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 1d3c9be245a5a..f20c97e443984 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -886,16 +886,15 @@ impl<'tcx> TypeVisitor> for IllegalSelfTypeVisitor<'tcx> { let ct = self.tcx.expand_abstract_consts(ct); match ct.kind() { - ty::ConstKind::Unevaluated( - proj @ ty::UnevaluatedConst { - kind: ty::UnevaluatedConstKind::Projection { .. }, - .. - }, - ) if self.tcx.features().min_generic_const_args() => { + ty::ConstKind::Unevaluated(ty::UnevaluatedConst { + kind: ty::UnevaluatedConstKind::Projection { def_id }, + args, + .. + }) if self.tcx.features().min_generic_const_args() => { match self.allow_self_projections { 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); + let trait_def_id = self.tcx.parent(def_id); + let trait_ref = ty::TraitRef::from_assoc(self.tcx, trait_def_id, args); // Only walk contained consts if the parent trait is not a supertrait. if self.is_supertrait_of_current_trait(trait_ref) { diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 11d743c209c7f..24e3eb7695976 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -559,11 +559,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { return ProcessResult::Changed(PendingPredicateObligations::new()); } ty::ConstKind::Value(cv) => cv.ty, - ty::ConstKind::Unevaluated(uv) => infcx - .tcx - .type_of(uv.kind.def_id()) - .instantiate(infcx.tcx, uv.args) - .skip_norm_wip(), + ty::ConstKind::Unevaluated(uv) => uv.type_of(infcx.tcx).skip_norm_wip(), // FIXME(generic_const_exprs): we should construct an alias like // `>::Output` when this is an `Expr` representing // `lhs + rhs`. diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index c37b50e47129a..678f1ee96abbb 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -606,8 +606,12 @@ pub fn try_evaluate_const<'tcx>( | ty::ConstKind::Placeholder(_) | ty::ConstKind::Expr(_) => Err(EvaluateConstErr::HasGenericsOrInfers), ty::ConstKind::Unevaluated(uv) => { - let opt_anon_const_kind = matches!(uv.kind, ty::UnevaluatedConstKind::Anon { .. }) - .then(|| tcx.anon_const_kind(uv.kind.def_id())); + let opt_anon_const_kind = match uv.kind { + ty::UnevaluatedConstKind::Anon { def_id } => { + Some((def_id, tcx.anon_const_kind(def_id))) + } + _ => None, + }; // Postpone evaluation of constants that depend on generic parameters or // inference variables. @@ -624,12 +628,12 @@ pub fn try_evaluate_const<'tcx>( // We handle `generic_const_exprs` separately as reasonable ways of handling constants in the type system // completely fall apart under `generic_const_exprs` and makes this whole function Really hard to reason // about if you have to consider gce whatsoever. - Some(ty::AnonConstKind::GCE) => { + Some((def_id, ty::AnonConstKind::GCE)) => { if uv.has_non_region_infer() || uv.has_non_region_param() { // `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.kind.def_id()) { + match tcx.thir_abstract_const(def_id) { Ok(Some(ct)) => { let ct = tcx.expand_abstract_consts( ct.instantiate(tcx, uv.args).skip_norm_wip(), @@ -650,9 +654,8 @@ pub fn try_evaluate_const<'tcx>( } } Err(_) | Ok(None) => { - let args = GenericArgs::identity_for_item(tcx, uv.kind.def_id()); - let typing_env = - ty::TypingEnv::post_analysis(tcx, uv.kind.def_id()); + let args = GenericArgs::identity_for_item(tcx, def_id); + let typing_env = ty::TypingEnv::post_analysis(tcx, def_id); (args, typing_env) } } @@ -663,7 +666,7 @@ pub fn try_evaluate_const<'tcx>( (uv.args, typing_env) } } - Some(ty::AnonConstKind::RepeatExprCount) => { + Some((def_id, ty::AnonConstKind::RepeatExprCount)) => { if uv.has_non_region_infer() { // Diagnostics will sometimes replace the identity args of anon consts in // array repeat expr counts with inference variables so we have to handle this @@ -680,14 +683,14 @@ 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.kind.def_id()); - let typing_env = ty::TypingEnv::post_analysis(tcx, uv.kind.def_id()); + let args = GenericArgs::identity_for_item(tcx, def_id); + let typing_env = ty::TypingEnv::post_analysis(tcx, def_id); (args, typing_env) } - Some(ty::AnonConstKind::GCA) - | Some(ty::AnonConstKind::MCG) - | Some(ty::AnonConstKind::NonTypeSystem) + Some((_, ty::AnonConstKind::GCA)) + | Some((_, ty::AnonConstKind::MCG)) + | Some((_, ty::AnonConstKind::NonTypeSystem)) | None => { // We are only dealing with "truly" generic/uninferred constants here: // - GCEConsts have been handled separately @@ -722,16 +725,9 @@ pub fn try_evaluate_const<'tcx>( 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.kind.def_id()), - ) { - Ok(Ok(val)) => Ok(ty::Const::new_value( - tcx, - val, - tcx.type_of(uv.kind.def_id()).instantiate(tcx, uv.args).skip_norm_wip(), - )), + let span = uv.kind.def_span(tcx); + match tcx.const_eval_resolve_for_typeck(typing_env, erased_uv, span) { + Ok(Ok(val)) => Ok(ty::Const::new_value(tcx, val, uv.type_of(tcx).skip_norm_wip())), Ok(Err(_)) => { let e = tcx.dcx().delayed_bug( "Type system constant with non valtree'able type evaluated but no error emitted", diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index d3bad276d5688..6346068a59174 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -449,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.kind.def_id())) + && !matches!(ct.kind(), ty::ConstKind::Unevaluated(uv) if uv.kind.is_type_const(tcx)) || !needs_normalization(self.selcx.infcx, &ct) { return ct; diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index d3fc3c30d5c3f..5f9aa3e50d968 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -987,11 +987,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } ty::ConstKind::Error(_) => return Ok(EvaluatedToOk), ty::ConstKind::Value(cv) => cv.ty, - ty::ConstKind::Unevaluated(uv) => self - .tcx() - .type_of(uv.kind.def_id()) - .instantiate(self.tcx(), uv.args) - .skip_norm_wip(), + ty::ConstKind::Unevaluated(uv) => uv.type_of(self.tcx()).skip_norm_wip(), // FIXME(generic_const_exprs): See comment in `fulfill.rs` ty::ConstKind::Expr(_) => return Ok(EvaluatedToOk), ty::ConstKind::Placeholder(_) => { diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 932f9c7e9b04e..c458a1cd15c3e 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -1064,8 +1064,7 @@ 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.kind.def_id()) && !tcx.features().generic_const_args() - { + if !uv.kind.is_type_const(tcx) && !tcx.features().generic_const_args() { let predicate = ty::Binder::dummy(ty::PredicateKind::Clause( ty::ClauseKind::ConstEvaluatable(c), )); @@ -1079,12 +1078,17 @@ impl<'a, 'tcx> TypeVisitor> for WfPredicates<'a, 'tcx> { )); } - 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.kind.def_id(), uv.args); - self.out.extend(obligations); + match uv.kind { + ty::UnevaluatedConstKind::Inherent { .. } => { + self.add_wf_preds_for_inherent_projection(uv.into()); + return; // Subtree is handled by above function + } + ty::UnevaluatedConstKind::Projection { def_id } + | ty::UnevaluatedConstKind::Free { def_id } + | ty::UnevaluatedConstKind::Anon { def_id } => { + let obligations = self.nominal_obligations(def_id, uv.args); + self.out.extend(obligations); + } } } } diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs index 37824447fc893..ddcdca9e2370d 100644 --- a/compiler/rustc_type_ir/src/const_kind.rs +++ b/compiler/rustc_type_ir/src/const_kind.rs @@ -94,9 +94,27 @@ impl UnevaluatedConst { kind: UnevaluatedConstKind, args: I::GenericArgs, ) -> UnevaluatedConst { - interner.debug_assert_args_compatible(kind.def_id(), args); + if cfg!(debug_assertions) { + let def_id = match kind { + ty::UnevaluatedConstKind::Projection { def_id } => def_id.into(), + ty::UnevaluatedConstKind::Inherent { def_id } => def_id.into(), + ty::UnevaluatedConstKind::Free { def_id } => def_id.into(), + ty::UnevaluatedConstKind::Anon { def_id } => def_id.into(), + }; + interner.debug_assert_args_compatible(def_id, args); + } UnevaluatedConst { kind, args, _use_unevaluated_const_new_instead: () } } + + pub fn type_of(self, interner: I) -> ty::Unnormalized { + let def_id = match self.kind { + ty::UnevaluatedConstKind::Projection { def_id } => def_id.into(), + ty::UnevaluatedConstKind::Inherent { def_id } => def_id.into(), + ty::UnevaluatedConstKind::Free { def_id } => def_id.into(), + ty::UnevaluatedConstKind::Anon { def_id } => def_id.into(), + }; + interner.type_of(def_id).instantiate(interner, self.args) + } } /// UnevaluatedConstKind is extremely similar to AliasTyKind, and likely should be reasoned about @@ -124,12 +142,30 @@ impl UnevaluatedConstKind { interner.unevaluated_const_kind_from_def_id(def_id) } - pub fn def_id(self) -> I::DefId { + pub fn is_type_const(self, interner: I) -> bool { + match self { + UnevaluatedConstKind::Projection { def_id } => interner.is_type_const(def_id.into()), + UnevaluatedConstKind::Inherent { def_id } => interner.is_type_const(def_id.into()), + UnevaluatedConstKind::Free { def_id } => interner.is_type_const(def_id.into()), + UnevaluatedConstKind::Anon { def_id } => interner.is_type_const(def_id.into()), + } + } + + pub fn def_span(self, interner: I) -> I::Span { + match self { + UnevaluatedConstKind::Projection { def_id } => interner.def_span(def_id.into()), + UnevaluatedConstKind::Inherent { def_id } => interner.def_span(def_id.into()), + UnevaluatedConstKind::Free { def_id } => interner.def_span(def_id.into()), + UnevaluatedConstKind::Anon { def_id } => interner.def_span(def_id.into()), + } + } + + pub fn opt_def_id(self) -> Option { 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::Projection { def_id } => Some(def_id.into()), + UnevaluatedConstKind::Inherent { def_id } => Some(def_id.into()), + UnevaluatedConstKind::Free { def_id } => Some(def_id.into()), + UnevaluatedConstKind::Anon { def_id } => Some(def_id.into()), } } } diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index a4737cf137b0c..e00d202acf289 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -239,6 +239,8 @@ pub trait Interner: fn const_of_item(self, def_id: Self::DefId) -> ty::EarlyBinder; fn anon_const_kind(self, def_id: Self::DefId) -> ty::AnonConstKind; + fn def_span(self, def_id: Self::DefId) -> Self::Span; + type AdtDef: AdtDef; fn adt_def(self, adt_def_id: Self::AdtId) -> Self::AdtDef; diff --git a/compiler/rustc_type_ir/src/relate.rs b/compiler/rustc_type_ir/src/relate.rs index e1df344d896d8..73870378f5ca0 100644 --- a/compiler/rustc_type_ir/src/relate.rs +++ b/compiler/rustc_type_ir/src/relate.rs @@ -225,7 +225,30 @@ impl Relate for ty::AliasTy { } else { relate_args_invariantly(relation, a.args, b.args)? }; - Ok(ty::AliasTy::new_from_args(relation.cx(), a.kind, args)) + Ok(ty::AliasTy::new_from_args(cx, a.kind, args)) + } + } +} + +impl Relate for ty::UnevaluatedConst { + fn relate>( + relation: &mut R, + a: ty::UnevaluatedConst, + b: ty::UnevaluatedConst, + ) -> RelateResult> { + let cx = relation.cx(); + if a.kind != b.kind { + Err(TypeError::ConstMismatch(ExpectedFound::new( + Const::new_unevaluated(cx, a), + Const::new_unevaluated(cx, b), + ))) + } else { + // FIXME(mgca): remove this + debug_assert_eq!(a.type_of(cx).skip_norm_wip(), b.type_of(cx).skip_norm_wip()); + + let args = relate_args_invariantly(relation, a.args, b.args)?; + + Ok(ty::UnevaluatedConst::new(cx, a.kind, args)) } } } @@ -591,21 +614,8 @@ 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.kind == bu.kind => { - // FIXME(mgca): remove this - if cfg!(debug_assertions) { - 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); - } - - let args = relation.relate_with_variance( - ty::Invariant, - VarianceDiagInfo::default(), - au.args, - bu.args, - )?; - return Ok(Const::new_unevaluated(cx, ty::UnevaluatedConst::new(cx, au.kind, args))); + (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) => { + return Ok(Const::new_unevaluated(cx, relation.relate(au, bu)?)); } (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 4367209f6f74d..f49840a4b21f9 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -350,15 +350,20 @@ 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 { 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, kind.def_id()) + ty::ConstKind::Unevaluated(ty::UnevaluatedConst { kind, .. }) => match kind { + ty::UnevaluatedConstKind::Projection { def_id } + | ty::UnevaluatedConstKind::Inherent { def_id } + | ty::UnevaluatedConstKind::Free { def_id } + | ty::UnevaluatedConstKind::Anon { def_id } => { + if let Some(local_def_id) = def_id.as_local() + && let Some(body_id) = tcx.hir_maybe_body_owned_by(local_def_id) + { + rendered_const(tcx, body_id, local_def_id) + } else { + inline::print_inlined_const(tcx, def_id) + } } - } + }, // array lengths are obviously usize ty::ConstKind::Value(cv) if *cv.ty.kind() == ty::Uint(ty::UintTy::Usize) => { cv.to_leaf().to_string()