From d0b760369f46eeb8ded4d7420d67d7bdc9f02dd1 Mon Sep 17 00:00:00 2001 From: mu001999 Date: Sat, 10 Jan 2026 17:06:21 +0800 Subject: [PATCH 1/5] Remove all usage of FeedConstTy::No --- .../src/hir_ty_lowering/bounds.rs | 34 ++++----- .../src/hir_ty_lowering/mod.rs | 53 +++++++++++--- compiler/rustc_hir_typeck/src/expr.rs | 5 +- src/librustdoc/clean/mod.rs | 70 ++++++++++++++++--- 4 files changed, 126 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index 72d21371f66cc..0a874b881801d 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -510,7 +510,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // Create the generic arguments for the associated type or constant by joining the // parent arguments (the arguments of the trait) and the own arguments (the ones of // the associated item itself) and construct an alias type using them. - let alias_term = candidate.map_bound(|trait_ref| { + candidate.map_bound(|trait_ref| { let item_segment = hir::PathSegment { ident: constraint.ident, hir_id: constraint.hir_id, @@ -528,20 +528,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { debug!(?alias_args); ty::AliasTerm::new_from_args(tcx, assoc_item.def_id, alias_args) - }); - - // Provide the resolved type of the associated constant to `type_of(AnonConst)`. - if let Some(const_arg) = constraint.ct() - && let hir::ConstArgKind::Anon(anon_const) = const_arg.kind - { - let ty = alias_term - .map_bound(|alias| tcx.type_of(alias.def_id).instantiate(tcx, alias.args)); - let ty = - check_assoc_const_binding_type(self, constraint.ident, ty, constraint.hir_id); - tcx.feed_anon_const_type(anon_const.def_id, ty::EarlyBinder::bind(ty)); - } - - alias_term + }) }; match constraint.kind { @@ -555,7 +542,20 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { hir::AssocItemConstraintKind::Equality { term } => { let term = match term { hir::Term::Ty(ty) => self.lower_ty(ty).into(), - hir::Term::Const(ct) => self.lower_const_arg(ct, FeedConstTy::No).into(), + hir::Term::Const(ct) => { + // Provide the resolved type of the associated constant + let ty = projection_term.map_bound(|alias| { + tcx.type_of(alias.def_id).instantiate(tcx, alias.args) + }); + let ty = check_assoc_const_binding_type( + self, + constraint.ident, + ty, + constraint.hir_id, + ); + + self.lower_const_arg(ct, FeedConstTy::WithTy(ty)).into() + } }; // Find any late-bound regions declared in `ty` that are not @@ -871,7 +871,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// probably gate this behind another feature flag. /// /// [^1]: . -fn check_assoc_const_binding_type<'tcx>( +pub(crate) fn check_assoc_const_binding_type<'tcx>( cx: &dyn HirTyLowerer<'tcx>, assoc_const: Ident, ty: ty::Binder<'tcx, Ty<'tcx>>, 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 d2cbf89336d8b..be5ac21e2ca84 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -1269,10 +1269,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let mut where_bounds = vec![]; for bound in [bound, bound2].into_iter().chain(matching_candidates) { let bound_id = bound.def_id(); - let bound_span = tcx - .associated_items(bound_id) - .find_by_ident_and_kind(tcx, assoc_ident, assoc_tag, bound_id) - .and_then(|item| tcx.hir_span_if_local(item.def_id)); + let assoc_item = tcx.associated_items(bound_id).find_by_ident_and_kind( + tcx, + assoc_ident, + assoc_tag, + bound_id, + ); + let bound_span = assoc_item.and_then(|item| tcx.hir_span_if_local(item.def_id)); if let Some(bound_span) = bound_span { err.span_label( @@ -1285,7 +1288,41 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let term: ty::Term<'_> = match term { hir::Term::Ty(ty) => self.lower_ty(ty).into(), hir::Term::Const(ct) => { - self.lower_const_arg(ct, FeedConstTy::No).into() + let assoc_item = + assoc_item.expect("assoc_item should be present"); + let projection_term = bound.map_bound(|trait_ref| { + let item_segment = hir::PathSegment { + ident: constraint.ident, + hir_id: constraint.hir_id, + res: Res::Err, + args: Some(constraint.gen_args), + infer_args: false, + }; + + let alias_args = self.lower_generic_args_of_assoc_item( + constraint.ident.span, + assoc_item.def_id, + &item_segment, + trait_ref.args, + ); + ty::AliasTerm::new_from_args( + tcx, + assoc_item.def_id, + alias_args, + ) + }); + + let ty = projection_term.map_bound(|alias| { + tcx.type_of(alias.def_id).instantiate(tcx, alias.args) + }); + let ty = bounds::check_assoc_const_binding_type( + self, + constraint.ident, + ty, + constraint.hir_id, + ); + + self.lower_const_arg(ct, FeedConstTy::WithTy(ty)).into() } }; if term.references_error() { @@ -2993,7 +3030,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .unwrap_or_else(|guar| Ty::new_error(tcx, guar)) } hir::TyKind::Array(ty, length) => { - let length = self.lower_const_arg(length, FeedConstTy::No); + let length = self.lower_const_arg(length, FeedConstTy::WithTy(tcx.types.usize)); Ty::new_array_with_const_len(tcx, self.lower_ty(ty), length) } hir::TyKind::Infer(()) => { @@ -3033,8 +3070,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // Keep this list of types in sync with the list of types that // the `RangePattern` trait is implemented for. ty::Int(_) | ty::Uint(_) | ty::Char => { - let start = self.lower_const_arg(start, FeedConstTy::No); - let end = self.lower_const_arg(end, FeedConstTy::No); + let start = self.lower_const_arg(start, FeedConstTy::WithTy(ty)); + let end = self.lower_const_arg(end, FeedConstTy::WithTy(ty)); Ok(ty::PatternKind::Range { start, end }) } _ => Err(self diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 9d7e09b020a75..d7366887d85c9 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1749,7 +1749,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let count_span = count.span; let count = self.try_structurally_resolve_const( count_span, - self.normalize(count_span, self.lower_const_arg(count, FeedConstTy::No)), + self.normalize( + count_span, + self.lower_const_arg(count, FeedConstTy::WithTy(tcx.types.usize)), + ), ); if let Some(count) = count.try_to_target_usize(tcx) { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 597a85f397695..ac17014ebfdeb 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -469,11 +469,23 @@ fn clean_middle_term<'tcx>( } } -fn clean_hir_term<'tcx>(term: &hir::Term<'tcx>, cx: &mut DocContext<'tcx>) -> Term { +fn clean_hir_term<'tcx>( + assoc_item: Option, + term: &hir::Term<'tcx>, + span: rustc_span::Span, + cx: &mut DocContext<'tcx>, +) -> Term { match term { hir::Term::Ty(ty) => Term::Type(clean_ty(ty, cx)), hir::Term::Const(c) => { - let ct = lower_const_arg_for_rustdoc(cx.tcx, c, FeedConstTy::No); + let ty = if let Some(assoc_item) = assoc_item { + // FIXME(generic_const_items): this should instantiate with the alias item's args + cx.tcx.type_of(assoc_item).instantiate_identity() + } else { + Ty::new_error_with_message(cx.tcx, span, "cannot find the associated constant") + }; + + let ct = lower_const_arg_for_rustdoc(cx.tcx, c, FeedConstTy::WithTy(ty)); Term::Constant(clean_middle_const(ty::Binder::dummy(ct), cx)) } } @@ -650,7 +662,14 @@ fn clean_generic_param<'tcx>( GenericParamDefKind::Const { ty: Box::new(clean_ty(ty, cx)), default: default.map(|ct| { - Box::new(lower_const_arg_for_rustdoc(cx.tcx, ct, FeedConstTy::No).to_string()) + Box::new( + lower_const_arg_for_rustdoc( + cx.tcx, + ct, + FeedConstTy::WithTy(lower_ty(cx.tcx, ty)), + ) + .to_string(), + ) }), }, ), @@ -1531,7 +1550,7 @@ fn first_non_private_clean_path<'tcx>( && path_last.args.is_some() { assert!(new_path_last.args.is_empty()); - new_path_last.args = clean_generic_args(path_last_args, cx); + new_path_last.args = clean_generic_args(None, path_last_args, cx); } new_clean_path } @@ -1812,7 +1831,11 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T let length = match const_arg.kind { hir::ConstArgKind::Infer(..) | hir::ConstArgKind::Error(..) => "_".to_string(), hir::ConstArgKind::Anon(hir::AnonConst { def_id, .. }) => { - let ct = lower_const_arg_for_rustdoc(cx.tcx, const_arg, FeedConstTy::No); + let ct = lower_const_arg_for_rustdoc( + cx.tcx, + const_arg, + FeedConstTy::WithTy(cx.tcx.types.usize), + ); let typing_env = ty::TypingEnv::post_analysis(cx.tcx, *def_id); let ct = cx.tcx.normalize_erasing_regions(typing_env, ct); print_const(cx, ct) @@ -1823,7 +1846,11 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T | hir::ConstArgKind::Tup(..) | hir::ConstArgKind::Array(..) | hir::ConstArgKind::Literal(..) => { - let ct = lower_const_arg_for_rustdoc(cx.tcx, const_arg, FeedConstTy::No); + let ct = lower_const_arg_for_rustdoc( + cx.tcx, + const_arg, + FeedConstTy::WithTy(cx.tcx.types.usize), + ); print_const(cx, ct) } }; @@ -2516,6 +2543,7 @@ fn clean_path<'tcx>(path: &hir::Path<'tcx>, cx: &mut DocContext<'tcx>) -> Path { } fn clean_generic_args<'tcx>( + trait_did: Option, generic_args: &hir::GenericArgs<'tcx>, cx: &mut DocContext<'tcx>, ) -> GenericArgs { @@ -2539,7 +2567,13 @@ fn clean_generic_args<'tcx>( let constraints = generic_args .constraints .iter() - .map(|c| clean_assoc_item_constraint(c, cx)) + .map(|c| { + clean_assoc_item_constraint( + trait_did.expect("only trait ref has constraints"), + c, + cx, + ) + }) .collect::>(); GenericArgs::AngleBracketed { args, constraints } } @@ -2562,7 +2596,11 @@ fn clean_path_segment<'tcx>( path: &hir::PathSegment<'tcx>, cx: &mut DocContext<'tcx>, ) -> PathSegment { - PathSegment { name: path.ident.name, args: clean_generic_args(path.args(), cx) } + let trait_did = match path.res { + hir::def::Res::Def(DefKind::Trait | DefKind::TraitAlias, did) => Some(did), + _ => None, + }; + PathSegment { name: path.ident.name, args: clean_generic_args(trait_did, path.args(), cx) } } fn clean_bare_fn_ty<'tcx>( @@ -3126,17 +3164,29 @@ fn clean_maybe_renamed_foreign_item<'tcx>( } fn clean_assoc_item_constraint<'tcx>( + trait_did: DefId, constraint: &hir::AssocItemConstraint<'tcx>, cx: &mut DocContext<'tcx>, ) -> AssocItemConstraint { AssocItemConstraint { assoc: PathSegment { name: constraint.ident.name, - args: clean_generic_args(constraint.gen_args, cx), + args: clean_generic_args(None, constraint.gen_args, cx), }, kind: match constraint.kind { hir::AssocItemConstraintKind::Equality { ref term } => { - AssocItemConstraintKind::Equality { term: clean_hir_term(term, cx) } + let assoc_tag = match term { + hir::Term::Ty(_) => ty::AssocTag::Type, + hir::Term::Const(_) => ty::AssocTag::Const, + }; + let assoc_item = cx + .tcx + .associated_items(trait_did) + .find_by_ident_and_kind(cx.tcx, constraint.ident, assoc_tag, trait_did) + .map(|item| item.def_id); + AssocItemConstraintKind::Equality { + term: clean_hir_term(assoc_item, term, constraint.span, cx), + } } hir::AssocItemConstraintKind::Bound { bounds } => AssocItemConstraintKind::Bound { bounds: bounds.iter().filter_map(|b| clean_generic_bound(b, cx)).collect(), From e27fcfd28eb6b185894e38d1f9fbde216f026f3e Mon Sep 17 00:00:00 2001 From: mu001999 Date: Sun, 11 Jan 2026 18:43:25 +0800 Subject: [PATCH 2/5] Remove FeedConstTy --- compiler/rustc_hir_analysis/src/collect.rs | 8 +- .../src/hir_ty_lowering/bounds.rs | 5 +- .../src/hir_ty_lowering/mod.rs | 89 +++++-------------- compiler/rustc_hir_analysis/src/lib.rs | 6 +- compiler/rustc_hir_typeck/src/expr.rs | 7 +- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 13 +-- .../rustc_hir_typeck/src/method/confirm.rs | 7 +- src/librustdoc/clean/mod.rs | 22 +---- 8 files changed, 48 insertions(+), 109 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index bacdf0049806e..2c02534093870 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -47,9 +47,7 @@ use rustc_trait_selection::traits::{ use tracing::{debug, instrument}; use crate::errors; -use crate::hir_ty_lowering::{ - FeedConstTy, HirTyLowerer, InherentAssocCandidate, RegionInferReason, -}; +use crate::hir_ty_lowering::{HirTyLowerer, InherentAssocCandidate, RegionInferReason}; pub(crate) mod dump; mod generics_of; @@ -1499,7 +1497,7 @@ fn const_param_default<'tcx>( let ct = icx .lowerer() - .lower_const_arg(default_ct, FeedConstTy::with_type_of(tcx, def_id, identity_args)); + .lower_const_arg(default_ct, tcx.type_of(def_id).instantiate(tcx, identity_args)); ty::EarlyBinder::bind(ct) } @@ -1557,7 +1555,7 @@ fn const_of_item<'tcx>( let identity_args = ty::GenericArgs::identity_for_item(tcx, def_id); let ct = icx .lowerer() - .lower_const_arg(ct_arg, FeedConstTy::with_type_of(tcx, def_id.to_def_id(), identity_args)); + .lower_const_arg(ct_arg, tcx.type_of(def_id.to_def_id()).instantiate(tcx, identity_args)); if let Err(e) = icx.check_tainted_by_errors() && !ct.references_error() { diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index 0a874b881801d..d6441702b268c 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -20,7 +20,7 @@ use tracing::{debug, instrument}; use crate::errors; use crate::hir_ty_lowering::{ - AssocItemQSelf, FeedConstTy, GenericsArgsErrExtend, HirTyLowerer, ImpliedBoundsContext, + AssocItemQSelf, GenericsArgsErrExtend, HirTyLowerer, ImpliedBoundsContext, OverlappingAsssocItemConstraints, PredicateFilter, RegionInferReason, }; @@ -543,7 +543,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let term = match term { hir::Term::Ty(ty) => self.lower_ty(ty).into(), hir::Term::Const(ct) => { - // Provide the resolved type of the associated constant let ty = projection_term.map_bound(|alias| { tcx.type_of(alias.def_id).instantiate(tcx, alias.args) }); @@ -554,7 +553,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { constraint.hir_id, ); - self.lower_const_arg(ct, FeedConstTy::WithTy(ty)).into() + self.lower_const_arg(ct, ty).into() } }; 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 be5ac21e2ca84..3dcc0232b301e 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -253,35 +253,6 @@ impl AssocItemQSelf { } } -/// In some cases, [`hir::ConstArg`]s that are being used in the type system -/// through const generics need to have their type "fed" to them -/// using the query system. -/// -/// Use this enum with `::lower_const_arg` to instruct it with the -/// desired behavior. -#[derive(Debug, Clone, Copy)] -pub enum FeedConstTy<'tcx> { - /// Feed the type to the (anno) const arg. - WithTy(Ty<'tcx>), - /// Don't feed the type. - No, -} - -impl<'tcx> FeedConstTy<'tcx> { - /// The `DefId` belongs to the const param that we are supplying - /// this (anon) const arg to. - /// - /// The list of generic args is used to instantiate the parameters - /// used by the type of the const param specified by `DefId`. - pub fn with_type_of( - tcx: TyCtxt<'tcx>, - def_id: DefId, - generic_args: &[ty::GenericArg<'tcx>], - ) -> Self { - Self::WithTy(tcx.type_of(def_id).instantiate(tcx, generic_args)) - } -} - #[derive(Debug, Clone, Copy)] enum LowerTypeRelativePathMode { Type(PermitVariants), @@ -733,7 +704,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // Ambig portions of `ConstArg` are handled in the match arm below .lower_const_arg( ct.as_unambig_ct(), - FeedConstTy::with_type_of(tcx, param.def_id, preceding_args), + tcx.type_of(param.def_id).instantiate(tcx, preceding_args), ) .into(), (&GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => { @@ -1322,7 +1293,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { constraint.hir_id, ); - self.lower_const_arg(ct, FeedConstTy::WithTy(ty)).into() + self.lower_const_arg(ct, ty).into() } }; if term.references_error() { @@ -2347,16 +2318,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// Lower a [`hir::ConstArg`] to a (type-level) [`ty::Const`](Const). #[instrument(skip(self), level = "debug")] - pub fn lower_const_arg( - &self, - const_arg: &hir::ConstArg<'tcx>, - feed: FeedConstTy<'tcx>, - ) -> Const<'tcx> { + pub fn lower_const_arg(&self, const_arg: &hir::ConstArg<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> { let tcx = self.tcx(); - if let FeedConstTy::WithTy(anon_const_type) = feed - && let hir::ConstArgKind::Anon(anon) = &const_arg.kind - { + if let hir::ConstArgKind::Anon(anon) = &const_arg.kind { // FIXME(generic_const_parameter_types): Ideally we remove these errors below when // we have the ability to intermix typeck of anon const const args with the parent // bodies typeck. @@ -2366,7 +2331,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // hir typeck was using equality but mir borrowck wound up using subtyping as that could // result in a non-infer in hir typeck but a region variable in borrowck. if tcx.features().generic_const_parameter_types() - && (anon_const_type.has_free_regions() || anon_const_type.has_erased_regions()) + && (ty.has_free_regions() || ty.has_erased_regions()) { let e = self.dcx().span_err( const_arg.span, @@ -2378,7 +2343,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // We must error if the instantiated type has any inference variables as we will // use this type to feed the `type_of` and query results must not contain inference // variables otherwise we will ICE. - if anon_const_type.has_non_region_infer() { + if ty.has_non_region_infer() { let e = self.dcx().span_err( const_arg.span, "anonymous constants with inferred types are not yet supported", @@ -2388,7 +2353,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } // We error when the type contains unsubstituted generics since we do not currently // give the anon const any of the generics from the parent. - if anon_const_type.has_non_region_param() { + if ty.has_non_region_param() { let e = self.dcx().span_err( const_arg.span, "anonymous constants referencing generics are not yet supported", @@ -2397,12 +2362,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { return ty::Const::new_error(tcx, e); } - tcx.feed_anon_const_type(anon.def_id, ty::EarlyBinder::bind(anon_const_type)); + tcx.feed_anon_const_type(anon.def_id, ty::EarlyBinder::bind(ty)); } let hir_id = const_arg.hir_id; match const_arg.kind { - hir::ConstArgKind::Tup(exprs) => self.lower_const_arg_tup(exprs, feed, const_arg.span), + hir::ConstArgKind::Tup(exprs) => self.lower_const_arg_tup(exprs, ty, const_arg.span), hir::ConstArgKind::Path(hir::QPath::Resolved(maybe_qself, path)) => { debug!(?maybe_qself, ?path); let opt_self_ty = maybe_qself.as_ref().map(|qself| self.lower_ty(qself)); @@ -2426,16 +2391,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { hir::ConstArgKind::TupleCall(qpath, args) => { self.lower_const_arg_tuple_call(hir_id, qpath, args, const_arg.span) } - hir::ConstArgKind::Array(array_expr) => self.lower_const_arg_array(array_expr, feed), + hir::ConstArgKind::Array(array_expr) => self.lower_const_arg_array(array_expr, ty), hir::ConstArgKind::Anon(anon) => self.lower_const_arg_anon(anon), hir::ConstArgKind::Infer(()) => self.ct_infer(None, const_arg.span), hir::ConstArgKind::Error(e) => ty::Const::new_error(tcx, e), - hir::ConstArgKind::Literal(kind) if let FeedConstTy::WithTy(anon_const_type) = feed => { - self.lower_const_arg_literal(&kind, anon_const_type, const_arg.span) - } - hir::ConstArgKind::Literal(..) => { - let e = self.dcx().span_err(const_arg.span, "literal of unknown type"); - ty::Const::new_error(tcx, e) + hir::ConstArgKind::Literal(kind) => { + self.lower_const_arg_literal(&kind, ty, const_arg.span) } } } @@ -2443,14 +2404,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { fn lower_const_arg_array( &self, array_expr: &'tcx hir::ConstArgArrayExpr<'tcx>, - feed: FeedConstTy<'tcx>, + ty: Ty<'tcx>, ) -> Const<'tcx> { let tcx = self.tcx(); - let FeedConstTy::WithTy(ty) = feed else { - return Const::new_error_with_message(tcx, array_expr.span, "unsupported const array"); - }; - let ty::Array(elem_ty, _) = ty.kind() else { return Const::new_error_with_message( tcx, @@ -2462,7 +2419,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let elems = array_expr .elems .iter() - .map(|elem| self.lower_const_arg(elem, FeedConstTy::WithTy(*elem_ty))) + .map(|elem| self.lower_const_arg(elem, *elem_ty)) .collect::>(); let valtree = ty::ValTree::from_branches(tcx, elems); @@ -2545,7 +2502,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .iter() .zip(args) .map(|(field_def, arg)| { - self.lower_const_arg(arg, FeedConstTy::with_type_of(tcx, field_def.did, adt_args)) + self.lower_const_arg(arg, tcx.type_of(field_def.did).instantiate(tcx, adt_args)) }) .collect::>(); @@ -2564,15 +2521,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { fn lower_const_arg_tup( &self, exprs: &'tcx [&'tcx hir::ConstArg<'tcx>], - feed: FeedConstTy<'tcx>, + ty: Ty<'tcx>, span: Span, ) -> Const<'tcx> { let tcx = self.tcx(); - let FeedConstTy::WithTy(ty) = feed else { - return Const::new_error_with_message(tcx, span, "const tuple lack type information"); - }; - let ty::Tuple(tys) = ty.kind() else { let e = tcx.dcx().span_err(span, format!("expected `{}`, found const tuple", ty)); return Const::new_error(tcx, e); @@ -2581,7 +2534,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let exprs = exprs .iter() .zip(tys.iter()) - .map(|(expr, ty)| self.lower_const_arg(expr, FeedConstTy::WithTy(ty))) + .map(|(expr, ty)| self.lower_const_arg(expr, ty)) .collect::>(); let valtree = ty::ValTree::from_branches(tcx, exprs); @@ -2668,7 +2621,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { self.lower_const_arg( expr.expr, - FeedConstTy::with_type_of(tcx, field_def.did, adt_args), + tcx.type_of(field_def.did).instantiate(tcx, adt_args), ) } None => { @@ -3030,7 +2983,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .unwrap_or_else(|guar| Ty::new_error(tcx, guar)) } hir::TyKind::Array(ty, length) => { - let length = self.lower_const_arg(length, FeedConstTy::WithTy(tcx.types.usize)); + let length = self.lower_const_arg(length, tcx.types.usize); Ty::new_array_with_const_len(tcx, self.lower_ty(ty), length) } hir::TyKind::Infer(()) => { @@ -3070,8 +3023,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // Keep this list of types in sync with the list of types that // the `RangePattern` trait is implemented for. ty::Int(_) | ty::Uint(_) | ty::Char => { - let start = self.lower_const_arg(start, FeedConstTy::WithTy(ty)); - let end = self.lower_const_arg(end, FeedConstTy::WithTy(ty)); + let start = self.lower_const_arg(start, ty); + let end = self.lower_const_arg(end, ty); Ok(ty::PatternKind::Range { start, end }) } _ => Err(self diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 7296ba6f964a4..a51355adf72fe 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -101,7 +101,7 @@ use rustc_span::{ErrorGuaranteed, Span}; use rustc_trait_selection::traits; pub use crate::collect::suggest_impl_trait; -use crate::hir_ty_lowering::{FeedConstTy, HirTyLowerer}; +use crate::hir_ty_lowering::HirTyLowerer; rustc_fluent_macro::fluent_messages! { "../messages.ftl" } @@ -301,8 +301,8 @@ pub fn lower_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> { pub fn lower_const_arg_for_rustdoc<'tcx>( tcx: TyCtxt<'tcx>, hir_ct: &hir::ConstArg<'tcx>, - feed: FeedConstTy<'tcx>, + ty: Ty<'tcx>, ) -> Const<'tcx> { let env_def_id = tcx.hir_get_parent_item(hir_ct.hir_id); - collect::ItemCtxt::new(tcx, env_def_id.def_id).lowerer().lower_const_arg(hir_ct, feed) + collect::ItemCtxt::new(tcx, env_def_id.def_id).lowerer().lower_const_arg(hir_ct, ty) } diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index d7366887d85c9..9f3ff0b2d03c2 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -21,7 +21,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; use rustc_hir::{ExprKind, HirId, QPath, find_attr, is_range_literal}; use rustc_hir_analysis::NoVariantNamed; -use rustc_hir_analysis::hir_ty_lowering::{FeedConstTy, HirTyLowerer as _}; +use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer as _; use rustc_infer::infer::{self, DefineOpaqueTypes, InferOk, RegionVariableOrigin}; use rustc_infer::traits::query::NoSolution; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase}; @@ -1749,10 +1749,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let count_span = count.span; let count = self.try_structurally_resolve_const( count_span, - self.normalize( - count_span, - self.lower_const_arg(count, FeedConstTy::WithTy(tcx.types.usize)), - ), + self.normalize(count_span, self.lower_const_arg(count, tcx.types.usize)), ); if let Some(count) = count.try_to_target_usize(tcx) { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index a66ff2a23c250..91f91d9114449 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -14,8 +14,8 @@ use rustc_hir_analysis::hir_ty_lowering::generics::{ check_generic_arg_count_for_call, lower_generic_args, }; use rustc_hir_analysis::hir_ty_lowering::{ - ExplicitLateBound, FeedConstTy, GenericArgCountMismatch, GenericArgCountResult, - GenericArgsLowerer, GenericPathSegment, HirTyLowerer, IsMethodCall, RegionInferReason, + ExplicitLateBound, GenericArgCountMismatch, GenericArgCountResult, GenericArgsLowerer, + GenericPathSegment, HirTyLowerer, IsMethodCall, RegionInferReason, }; use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse}; use rustc_infer::infer::{DefineOpaqueTypes, InferResult}; @@ -525,9 +525,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(crate) fn lower_const_arg( &self, const_arg: &'tcx hir::ConstArg<'tcx>, - feed: FeedConstTy<'tcx>, + ty: Ty<'tcx>, ) -> ty::Const<'tcx> { - let ct = self.lowerer().lower_const_arg(const_arg, feed); + let ct = self.lowerer().lower_const_arg(const_arg, ty); self.register_wf_obligation( ct.into(), self.tcx.hir_span(const_arg.hir_id), @@ -1228,7 +1228,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Ambiguous parts of `ConstArg` are handled in the match arms below .lower_const_arg( ct.as_unambig_ct(), - FeedConstTy::with_type_of(self.fcx.tcx, param.def_id, preceding_args), + self.fcx + .tcx + .type_of(param.def_id) + .instantiate(self.fcx.tcx, preceding_args), ) .into(), (&GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => { diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index aab4e39855557..270f011b2b15f 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -7,7 +7,7 @@ use rustc_hir_analysis::hir_ty_lowering::generics::{ check_generic_arg_count_for_call, lower_generic_args, }; use rustc_hir_analysis::hir_ty_lowering::{ - FeedConstTy, GenericArgsLowerer, HirTyLowerer, IsMethodCall, RegionInferReason, + GenericArgsLowerer, HirTyLowerer, IsMethodCall, RegionInferReason, }; use rustc_infer::infer::{ BoundRegionConversionTime, DefineOpaqueTypes, InferOk, RegionVariableOrigin, @@ -447,7 +447,10 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { // We handle the ambig portions of `ConstArg` in the match arms below .lower_const_arg( ct.as_unambig_ct(), - FeedConstTy::with_type_of(self.cfcx.tcx, param.def_id, preceding_args), + self.cfcx + .tcx + .type_of(param.def_id) + .instantiate(self.cfcx.tcx, preceding_args), ) .into(), (GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index ac17014ebfdeb..c7c23f75d6943 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -43,7 +43,6 @@ use rustc_hir::attrs::{AttributeKind, DocAttribute, DocInline}; use rustc_hir::def::{CtorKind, DefKind, MacroKinds, Res}; use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LOCAL_CRATE, LocalDefId}; use rustc_hir::{LangItem, PredicateOrigin, find_attr}; -use rustc_hir_analysis::hir_ty_lowering::FeedConstTy; use rustc_hir_analysis::{lower_const_arg_for_rustdoc, lower_ty}; use rustc_middle::metadata::Reexport; use rustc_middle::middle::resolve_bound_vars as rbv; @@ -485,7 +484,7 @@ fn clean_hir_term<'tcx>( Ty::new_error_with_message(cx.tcx, span, "cannot find the associated constant") }; - let ct = lower_const_arg_for_rustdoc(cx.tcx, c, FeedConstTy::WithTy(ty)); + let ct = lower_const_arg_for_rustdoc(cx.tcx, c, ty); Term::Constant(clean_middle_const(ty::Binder::dummy(ct), cx)) } } @@ -663,12 +662,7 @@ fn clean_generic_param<'tcx>( ty: Box::new(clean_ty(ty, cx)), default: default.map(|ct| { Box::new( - lower_const_arg_for_rustdoc( - cx.tcx, - ct, - FeedConstTy::WithTy(lower_ty(cx.tcx, ty)), - ) - .to_string(), + lower_const_arg_for_rustdoc(cx.tcx, ct, lower_ty(cx.tcx, ty)).to_string(), ) }), }, @@ -1831,11 +1825,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T let length = match const_arg.kind { hir::ConstArgKind::Infer(..) | hir::ConstArgKind::Error(..) => "_".to_string(), hir::ConstArgKind::Anon(hir::AnonConst { def_id, .. }) => { - let ct = lower_const_arg_for_rustdoc( - cx.tcx, - const_arg, - FeedConstTy::WithTy(cx.tcx.types.usize), - ); + let ct = lower_const_arg_for_rustdoc(cx.tcx, const_arg, cx.tcx.types.usize); let typing_env = ty::TypingEnv::post_analysis(cx.tcx, *def_id); let ct = cx.tcx.normalize_erasing_regions(typing_env, ct); print_const(cx, ct) @@ -1846,11 +1836,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T | hir::ConstArgKind::Tup(..) | hir::ConstArgKind::Array(..) | hir::ConstArgKind::Literal(..) => { - let ct = lower_const_arg_for_rustdoc( - cx.tcx, - const_arg, - FeedConstTy::WithTy(cx.tcx.types.usize), - ); + let ct = lower_const_arg_for_rustdoc(cx.tcx, const_arg, cx.tcx.types.usize); print_const(cx, ct) } }; From 37f20b7631c6a6c712f0c19a91531623282d6507 Mon Sep 17 00:00:00 2001 From: mu001999 Date: Sun, 11 Jan 2026 21:02:00 +0800 Subject: [PATCH 3/5] Bless tests --- .../associated-const-bindings/ambiguity.stderr | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/ui/const-generics/associated-const-bindings/ambiguity.stderr b/tests/ui/const-generics/associated-const-bindings/ambiguity.stderr index a14afe9d6923b..806708f18d654 100644 --- a/tests/ui/const-generics/associated-const-bindings/ambiguity.stderr +++ b/tests/ui/const-generics/associated-const-bindings/ambiguity.stderr @@ -27,6 +27,12 @@ LL | const C: &'static str; ... LL | fn take1(_: impl Trait1) {} | ^^^^^^^ ambiguous associated constant `C` + | + = help: consider introducing a new type parameter `T` and adding `where` constraints: + where + T: Trait1, + T: Parent2::C = "?", + T: Parent1::C = "?" error: aborting due to 2 previous errors From 80bd069138feba6452059852785bb913a7dba66c Mon Sep 17 00:00:00 2001 From: mu001999 Date: Mon, 12 Jan 2026 23:50:32 +0800 Subject: [PATCH 4/5] Fix review comments --- .../rustc_hir_analysis/src/hir_ty_lowering/mod.rs | 2 ++ src/librustdoc/clean/mod.rs | 14 +++----------- 2 files changed, 5 insertions(+), 11 deletions(-) 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 3dcc0232b301e..65d2d61e6fc45 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -1283,6 +1283,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) }); + // FIXME(mgca): code duplication with other places we lower + // the rhs' of associated const bindings let ty = projection_term.map_bound(|alias| { tcx.type_of(alias.def_id).instantiate(tcx, alias.args) }); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index c7c23f75d6943..0ad9d2fdbe804 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -471,19 +471,13 @@ fn clean_middle_term<'tcx>( fn clean_hir_term<'tcx>( assoc_item: Option, term: &hir::Term<'tcx>, - span: rustc_span::Span, cx: &mut DocContext<'tcx>, ) -> Term { match term { hir::Term::Ty(ty) => Term::Type(clean_ty(ty, cx)), hir::Term::Const(c) => { - let ty = if let Some(assoc_item) = assoc_item { - // FIXME(generic_const_items): this should instantiate with the alias item's args - cx.tcx.type_of(assoc_item).instantiate_identity() - } else { - Ty::new_error_with_message(cx.tcx, span, "cannot find the associated constant") - }; - + // FIXME(generic_const_items): this should instantiate with the alias item's args + let ty = cx.tcx.type_of(assoc_item.unwrap()).instantiate_identity(); let ct = lower_const_arg_for_rustdoc(cx.tcx, c, ty); Term::Constant(clean_middle_const(ty::Binder::dummy(ct), cx)) } @@ -3170,9 +3164,7 @@ fn clean_assoc_item_constraint<'tcx>( .associated_items(trait_did) .find_by_ident_and_kind(cx.tcx, constraint.ident, assoc_tag, trait_did) .map(|item| item.def_id); - AssocItemConstraintKind::Equality { - term: clean_hir_term(assoc_item, term, constraint.span, cx), - } + AssocItemConstraintKind::Equality { term: clean_hir_term(assoc_item, term, cx) } } hir::AssocItemConstraintKind::Bound { bounds } => AssocItemConstraintKind::Bound { bounds: bounds.iter().filter_map(|b| clean_generic_bound(b, cx)).collect(), From 12b4b72715b5814ab48fc4c78169fd6cef0ccc25 Mon Sep 17 00:00:00 2001 From: mu001999 Date: Tue, 13 Jan 2026 20:53:48 +0800 Subject: [PATCH 5/5] Add test for issue 151048 --- .../mgca/tuple_expr_arg_bad-issue-151048.rs | 8 ++++++++ .../mgca/tuple_expr_arg_bad-issue-151048.stderr | 8 ++++++++ 2 files changed, 16 insertions(+) create mode 100644 tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.rs create mode 100644 tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.stderr diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.rs b/tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.rs new file mode 100644 index 0000000000000..4aecd30e86bbb --- /dev/null +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.rs @@ -0,0 +1,8 @@ +#![feature(min_generic_const_args)] +#![expect(incomplete_features)] + +struct Y { + stuff: [u8; { ([1, 2], 3, [4, 5]) }], //~ ERROR expected `usize`, found const tuple +} + +fn main() {} diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.stderr b/tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.stderr new file mode 100644 index 0000000000000..468bf703d90d4 --- /dev/null +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.stderr @@ -0,0 +1,8 @@ +error: expected `usize`, found const tuple + --> $DIR/tuple_expr_arg_bad-issue-151048.rs:5:19 + | +LL | stuff: [u8; { ([1, 2], 3, [4, 5]) }], + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error +