Rollup merge of #150962 - rm/feed_const_ty, r=BoxyUwU

Remove `FeedConstTy` and provide ty when lowering const arg

r? @BoxyUwU

edit: BoxyUwU

`FeedConstTy` currently only provides the expected type of a const argument *sometimes* (e.g. previously array lengths did not do this). This causes problems with mGCA's directly represented const arguments which always need to know their expected type.
This commit is contained in:
Jonathan Brouwer 2026-01-14 22:29:57 +01:00 committed by GitHub
commit 27e6ef9f6d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 163 additions and 118 deletions

View file

@ -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()
{

View file

@ -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,
};
@ -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,19 @@ 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) => {
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, ty).into()
}
};
// Find any late-bound regions declared in `ty` that are not
@ -871,7 +870,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
/// probably gate this behind another feature flag.
///
/// [^1]: <https://github.com/rust-lang/project-const-generics/issues/28>.
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>>,

View file

@ -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 `<dyn HirTyLowerer>::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)) => {
@ -1269,10 +1240,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 +1259,43 @@ 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,
)
});
// 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)
});
let ty = bounds::check_assoc_const_binding_type(
self,
constraint.ident,
ty,
constraint.hir_id,
);
self.lower_const_arg(ct, ty).into()
}
};
if term.references_error() {
@ -2310,16 +2320,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.
@ -2329,7 +2333,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,
@ -2341,7 +2345,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",
@ -2351,7 +2355,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",
@ -2360,12 +2364,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));
@ -2389,16 +2393,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)
}
}
}
@ -2406,14 +2406,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 {
let e = tcx
.dcx()
@ -2424,7 +2420,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::<Vec<_>>();
let valtree = ty::ValTree::from_branches(tcx, elems);
@ -2507,7 +2503,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::<Vec<_>>();
@ -2526,15 +2522,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);
@ -2543,7 +2535,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::<Vec<_>>();
let valtree = ty::ValTree::from_branches(tcx, exprs);
@ -2630,7 +2622,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 => {
@ -2992,7 +2984,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, tcx.types.usize);
Ty::new_array_with_const_len(tcx, self.lower_ty(ty), length)
}
hir::TyKind::Infer(()) => {
@ -3032,8 +3024,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, ty);
let end = self.lower_const_arg(end, ty);
Ok(ty::PatternKind::Range { start, end })
}
_ => Err(self

View file

@ -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)
}

View file

@ -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,7 +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::No)),
self.normalize(count_span, self.lower_const_arg(count, tcx.types.usize)),
);
if let Some(count) = count.try_to_target_usize(tcx) {

View file

@ -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)) => {

View file

@ -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)) => {

View file

@ -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;
@ -469,11 +468,17 @@ 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<DefId>,
term: &hir::Term<'tcx>,
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);
// 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))
}
}
@ -650,7 +655,9 @@ 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, lower_ty(cx.tcx, ty)).to_string(),
)
}),
},
),
@ -1531,7 +1538,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 +1819,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::No);
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)
@ -1823,7 +1830,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::No);
let ct = lower_const_arg_for_rustdoc(cx.tcx, const_arg, cx.tcx.types.usize);
print_const(cx, ct)
}
};
@ -2516,6 +2523,7 @@ fn clean_path<'tcx>(path: &hir::Path<'tcx>, cx: &mut DocContext<'tcx>) -> Path {
}
fn clean_generic_args<'tcx>(
trait_did: Option<DefId>,
generic_args: &hir::GenericArgs<'tcx>,
cx: &mut DocContext<'tcx>,
) -> GenericArgs {
@ -2539,7 +2547,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::<ThinVec<_>>();
GenericArgs::AngleBracketed { args, constraints }
}
@ -2562,7 +2576,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 +3144,27 @@ 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, cx) }
}
hir::AssocItemConstraintKind::Bound { bounds } => AssocItemConstraintKind::Bound {
bounds: bounds.iter().filter_map(|b| clean_generic_bound(b, cx)).collect(),

View file

@ -27,6 +27,12 @@ LL | const C: &'static str;
...
LL | fn take1(_: impl Trait1<C = "?">) {}
| ^^^^^^^ 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

View file

@ -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() {}

View file

@ -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