Skip to content

Commit a5c8e99

Browse files
committed
Move Const::from_const_arg to HIR ty lowering
This makes more sense and will allow us to start lowering all paths to `ConstArgKind::Path`, rather than just bare params.
1 parent ebf9bfc commit a5c8e99

File tree

9 files changed

+129
-116
lines changed

9 files changed

+129
-116
lines changed

compiler/rustc_hir_analysis/src/collect.rs

+21-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ use tracing::{debug, instrument};
4646

4747
use crate::check::intrinsic::intrinsic_operation_unsafety;
4848
use crate::errors;
49-
use crate::hir_ty_lowering::{HirTyLowerer, RegionInferReason};
49+
use crate::hir_ty_lowering::{FeedConstTy, HirTyLowerer, RegionInferReason};
5050

5151
pub(crate) mod dump;
5252
mod generics_of;
@@ -86,6 +86,7 @@ pub fn provide(providers: &mut Providers) {
8686
coroutine_for_closure,
8787
is_type_alias_impl_trait,
8888
rendered_precise_capturing_args,
89+
const_param_default,
8990
..*providers
9091
};
9192
}
@@ -1873,3 +1874,22 @@ fn rendered_precise_capturing_args<'tcx>(
18731874
_ => None,
18741875
})
18751876
}
1877+
1878+
fn const_param_default<'tcx>(
1879+
tcx: TyCtxt<'tcx>,
1880+
def_id: LocalDefId,
1881+
) -> ty::EarlyBinder<'tcx, Const<'tcx>> {
1882+
let default_ct = match tcx.hir_node_by_def_id(def_id) {
1883+
hir::Node::GenericParam(hir::GenericParam {
1884+
kind: hir::GenericParamKind::Const { default: Some(ct), .. },
1885+
..
1886+
}) => ct,
1887+
_ => span_bug!(
1888+
tcx.def_span(def_id),
1889+
"`const_param_default` expected a generic parameter with a constant"
1890+
),
1891+
};
1892+
let icx = ItemCtxt::new(tcx, def_id);
1893+
let ct = icx.lowerer().lower_const_arg(default_ct, FeedConstTy::No);
1894+
ty::EarlyBinder::bind(ct)
1895+
}

compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use super::errors::GenericsArgsErrExtend;
2020
use crate::bounds::Bounds;
2121
use crate::errors;
2222
use crate::hir_ty_lowering::{
23-
AssocItemQSelf, HirTyLowerer, OnlySelfBounds, PredicateFilter, RegionInferReason,
23+
AssocItemQSelf, FeedConstTy, HirTyLowerer, OnlySelfBounds, PredicateFilter, RegionInferReason,
2424
};
2525

2626
impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
@@ -392,9 +392,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
392392
hir::AssocItemConstraintKind::Equality { term } => {
393393
let term = match term {
394394
hir::Term::Ty(ty) => self.lower_ty(ty).into(),
395-
hir::Term::Const(ct) => {
396-
ty::Const::from_const_arg(tcx, ct, ty::FeedConstTy::No).into()
397-
}
395+
hir::Term::Const(ct) => self.lower_const_arg(ct, FeedConstTy::No).into(),
398396
};
399397

400398
// Find any late-bound regions declared in `ty` that are not

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

+74-5
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,23 @@ impl AssocItemQSelf {
212212
}
213213
}
214214

215+
/// In some cases, [`hir::ConstArg`]s that are being used in the type system
216+
/// through const generics need to have their type "fed" to them
217+
/// using the query system.
218+
///
219+
/// Use this enum with [`Const::from_const_arg`] to instruct it with the
220+
/// desired behavior.
221+
#[derive(Debug, Clone, Copy)]
222+
pub enum FeedConstTy {
223+
/// Feed the type.
224+
///
225+
/// The `DefId` belongs to the const param that we are supplying
226+
/// this (anon) const arg to.
227+
Param(DefId),
228+
/// Don't feed the type.
229+
No,
230+
}
231+
215232
/// New-typed boolean indicating whether explicit late-bound lifetimes
216233
/// are present in a set of generic arguments.
217234
///
@@ -495,8 +512,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
495512
handle_ty_args(has_default, &inf.to_ty())
496513
}
497514
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
498-
ty::Const::from_const_arg(tcx, ct, ty::FeedConstTy::Param(param.def_id))
499-
.into()
515+
self.lowerer.lower_const_arg(ct, FeedConstTy::Param(param.def_id)).into()
500516
}
501517
(&GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => {
502518
self.lowerer.ct_infer(Some(param), inf.span).into()
@@ -930,8 +946,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
930946
let term: ty::Term<'_> = match term {
931947
hir::Term::Ty(ty) => self.lower_ty(ty).into(),
932948
hir::Term::Const(ct) => {
933-
ty::Const::from_const_arg(tcx, ct, ty::FeedConstTy::No)
934-
.into()
949+
self.lower_const_arg(ct, FeedConstTy::No).into()
935950
}
936951
};
937952
// FIXME(#97583): This isn't syntactically well-formed!
@@ -2007,6 +2022,60 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
20072022
}
20082023
}
20092024

2025+
/// Convert a [`hir::ConstArg`] to a [`ty::Const`](Const).
2026+
#[instrument(skip(self), level = "debug")]
2027+
pub fn lower_const_arg(
2028+
&self,
2029+
const_arg: &hir::ConstArg<'tcx>,
2030+
feed: FeedConstTy,
2031+
) -> Const<'tcx> {
2032+
let tcx = self.tcx();
2033+
2034+
if let FeedConstTy::Param(param_def_id) = feed
2035+
&& let hir::ConstArgKind::Anon(anon) = &const_arg.kind
2036+
{
2037+
tcx.feed_anon_const_type(anon.def_id, tcx.type_of(param_def_id));
2038+
}
2039+
2040+
match const_arg.kind {
2041+
hir::ConstArgKind::Path(qpath) => {
2042+
// FIXME(min_generic_const_args): for now only params are lowered to ConstArgKind::Path
2043+
self.lower_const_arg_param(qpath, const_arg.hir_id)
2044+
}
2045+
hir::ConstArgKind::Anon(anon) => Const::from_anon_const(tcx, anon.def_id),
2046+
}
2047+
}
2048+
2049+
/// Lower a use of a const param to a [`Const`].
2050+
///
2051+
/// IMPORTANT: `qpath` must be a const param, otherwise this will panic
2052+
fn lower_const_arg_param(&self, qpath: hir::QPath<'tcx>, hir_id: HirId) -> Const<'tcx> {
2053+
let tcx = self.tcx();
2054+
2055+
let hir::QPath::Resolved(_, &hir::Path { res: Res::Def(DefKind::ConstParam, def_id), .. }) =
2056+
qpath
2057+
else {
2058+
span_bug!(qpath.span(), "non-param {qpath:?} passed to Const::from_param")
2059+
};
2060+
2061+
match tcx.named_bound_var(hir_id) {
2062+
Some(rbv::ResolvedArg::EarlyBound(_)) => {
2063+
// Find the name and index of the const parameter by indexing the generics of
2064+
// the parent item and construct a `ParamConst`.
2065+
let item_def_id = tcx.parent(def_id);
2066+
let generics = tcx.generics_of(item_def_id);
2067+
let index = generics.param_def_id_to_index[&def_id];
2068+
let name = tcx.item_name(def_id);
2069+
ty::Const::new_param(tcx, ty::ParamConst::new(index, name))
2070+
}
2071+
Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => {
2072+
ty::Const::new_bound(tcx, debruijn, ty::BoundVar::from_u32(index))
2073+
}
2074+
Some(rbv::ResolvedArg::Error(guar)) => ty::Const::new_error(tcx, guar),
2075+
arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", hir_id),
2076+
}
2077+
}
2078+
20102079
fn lower_delegation_ty(&self, idx: hir::InferDelegationKind) -> Ty<'tcx> {
20112080
let delegation_sig = self.tcx().inherit_sig_for_delegation_item(self.item_def_id());
20122081
match idx {
@@ -2146,7 +2215,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
21462215
let length = match length {
21472216
hir::ArrayLen::Infer(inf) => self.ct_infer(None, inf.span),
21482217
hir::ArrayLen::Body(constant) => {
2149-
ty::Const::from_const_arg(tcx, constant, ty::FeedConstTy::No)
2218+
self.lower_const_arg(constant, FeedConstTy::No)
21502219
}
21512220
};
21522221

compiler/rustc_hir_analysis/src/lib.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -96,13 +96,15 @@ use rustc_hir::def::DefKind;
9696
use rustc_middle::middle;
9797
use rustc_middle::mir::interpret::GlobalId;
9898
use rustc_middle::query::Providers;
99-
use rustc_middle::ty::{self, Ty, TyCtxt};
99+
use rustc_middle::ty::{self, Const, Ty, TyCtxt};
100100
use rustc_session::parse::feature_err;
101101
use rustc_span::Span;
102102
use rustc_span::symbol::sym;
103103
use rustc_target::spec::abi::Abi;
104104
use rustc_trait_selection::traits;
105105

106+
use self::hir_ty_lowering::{FeedConstTy, HirTyLowerer};
107+
106108
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
107109

108110
fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi, span: Span) {
@@ -227,3 +229,13 @@ pub fn lower_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
227229
let env_def_id = tcx.hir().get_parent_item(hir_ty.hir_id);
228230
collect::ItemCtxt::new(tcx, env_def_id.def_id).lower_ty(hir_ty)
229231
}
232+
233+
/// This is for rustdoc and clippy.
234+
pub fn lower_const_arg<'tcx>(
235+
tcx: TyCtxt<'tcx>,
236+
hir_ct: &hir::ConstArg<'tcx>,
237+
feed: FeedConstTy,
238+
) -> Const<'tcx> {
239+
let env_def_id = tcx.hir().get_parent_item(hir_ct.hir_id);
240+
collect::ItemCtxt::new(tcx, env_def_id.def_id).lowerer().lower_const_arg(hir_ct, feed)
241+
}

compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ use rustc_hir_analysis::hir_ty_lowering::generics::{
1313
check_generic_arg_count_for_call, lower_generic_args,
1414
};
1515
use rustc_hir_analysis::hir_ty_lowering::{
16-
ExplicitLateBound, GenericArgCountMismatch, GenericArgCountResult, GenericArgsLowerer,
17-
GenericPathSegment, HirTyLowerer, IsMethodCall, RegionInferReason,
16+
ExplicitLateBound, FeedConstTy, GenericArgCountMismatch, GenericArgCountResult,
17+
GenericArgsLowerer, GenericPathSegment, HirTyLowerer, IsMethodCall, RegionInferReason,
1818
};
1919
use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse};
2020
use rustc_infer::infer::{DefineOpaqueTypes, InferResult};
@@ -477,7 +477,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
477477
hir::ArrayLen::Infer(inf) => self.ct_infer(None, inf.span),
478478
hir::ArrayLen::Body(const_arg) => {
479479
let span = const_arg.span();
480-
let c = ty::Const::from_const_arg(self.tcx, const_arg, ty::FeedConstTy::No);
480+
let c = self.lowerer().lower_const_arg(const_arg, FeedConstTy::No);
481481
self.register_wf_obligation(c.into(), span, ObligationCauseCode::WellFormed(None));
482482
self.normalize(span, c)
483483
}
@@ -489,8 +489,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
489489
const_arg: &'tcx hir::ConstArg<'tcx>,
490490
param_def_id: DefId,
491491
) -> ty::Const<'tcx> {
492-
let ct =
493-
ty::Const::from_const_arg(self.tcx, const_arg, ty::FeedConstTy::Param(param_def_id));
492+
let ct = self.lowerer().lower_const_arg(const_arg, FeedConstTy::Param(param_def_id));
494493
self.register_wf_obligation(
495494
ct.into(),
496495
self.tcx.hir().span(const_arg.hir_id),

compiler/rustc_middle/src/ty/consts.rs

+2-87
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,12 @@ use either::Either;
22
use rustc_data_structures::intern::Interned;
33
use rustc_error_messages::MultiSpan;
44
use rustc_hir::def::{DefKind, Res};
5-
use rustc_hir::def_id::{DefId, LocalDefId};
6-
use rustc_hir::{self as hir, HirId};
5+
use rustc_hir::def_id::LocalDefId;
6+
use rustc_hir::{self as hir};
77
use rustc_macros::HashStable;
88
use rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo};
99
use tracing::{debug, instrument};
1010

11-
use crate::middle::resolve_bound_vars as rbv;
1211
use crate::mir::interpret::{ErrorHandled, LitToConstInput, Scalar};
1312
use crate::ty::{self, GenericArgs, ParamEnv, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt};
1413

@@ -183,46 +182,7 @@ impl<'tcx> rustc_type_ir::inherent::Const<TyCtxt<'tcx>> for Const<'tcx> {
183182
}
184183
}
185184

186-
/// In some cases, [`hir::ConstArg`]s that are being used in the type system
187-
/// through const generics need to have their type "fed" to them
188-
/// using the query system.
189-
///
190-
/// Use this enum with [`Const::from_const_arg`] to instruct it with the
191-
/// desired behavior.
192-
#[derive(Debug, Clone, Copy)]
193-
pub enum FeedConstTy {
194-
/// Feed the type.
195-
///
196-
/// The `DefId` belongs to the const param that we are supplying
197-
/// this (anon) const arg to.
198-
Param(DefId),
199-
/// Don't feed the type.
200-
No,
201-
}
202-
203185
impl<'tcx> Const<'tcx> {
204-
/// Convert a [`hir::ConstArg`] to a [`ty::Const`](Self).
205-
#[instrument(skip(tcx), level = "debug")]
206-
pub fn from_const_arg(
207-
tcx: TyCtxt<'tcx>,
208-
const_arg: &'tcx hir::ConstArg<'tcx>,
209-
feed: FeedConstTy,
210-
) -> Self {
211-
if let FeedConstTy::Param(param_def_id) = feed
212-
&& let hir::ConstArgKind::Anon(anon) = &const_arg.kind
213-
{
214-
tcx.feed_anon_const_type(anon.def_id, tcx.type_of(param_def_id));
215-
}
216-
217-
match const_arg.kind {
218-
hir::ConstArgKind::Path(qpath) => {
219-
// FIXME(min_generic_const_args): for now only params are lowered to ConstArgKind::Path
220-
Self::from_param(tcx, qpath, const_arg.hir_id)
221-
}
222-
hir::ConstArgKind::Anon(anon) => Self::from_anon_const(tcx, anon.def_id),
223-
}
224-
}
225-
226186
/// Literals and const generic parameters are eagerly converted to a constant, everything else
227187
/// becomes `Unevaluated`.
228188
#[instrument(skip(tcx), level = "debug")]
@@ -249,34 +209,6 @@ impl<'tcx> Const<'tcx> {
249209
}
250210
}
251211

252-
/// Lower a const param to a [`Const`].
253-
///
254-
/// IMPORTANT: `qpath` must be a const param, otherwise this will panic
255-
fn from_param(tcx: TyCtxt<'tcx>, qpath: hir::QPath<'tcx>, hir_id: HirId) -> Self {
256-
let hir::QPath::Resolved(_, &hir::Path { res: Res::Def(DefKind::ConstParam, def_id), .. }) =
257-
qpath
258-
else {
259-
span_bug!(qpath.span(), "non-param {qpath:?} passed to Const::from_param")
260-
};
261-
262-
match tcx.named_bound_var(hir_id) {
263-
Some(rbv::ResolvedArg::EarlyBound(_)) => {
264-
// Find the name and index of the const parameter by indexing the generics of
265-
// the parent item and construct a `ParamConst`.
266-
let item_def_id = tcx.parent(def_id);
267-
let generics = tcx.generics_of(item_def_id);
268-
let index = generics.param_def_id_to_index[&def_id];
269-
let name = tcx.item_name(def_id);
270-
ty::Const::new_param(tcx, ty::ParamConst::new(index, name))
271-
}
272-
Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => {
273-
ty::Const::new_bound(tcx, debruijn, ty::BoundVar::from_u32(index))
274-
}
275-
Some(rbv::ResolvedArg::Error(guar)) => ty::Const::new_error(tcx, guar),
276-
arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", hir_id),
277-
}
278-
}
279-
280212
#[instrument(skip(tcx), level = "debug")]
281213
fn try_from_lit(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, expr: &'tcx hir::Expr<'tcx>) -> Option<Self> {
282214
// Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments
@@ -527,20 +459,3 @@ impl<'tcx> Const<'tcx> {
527459
matches!(self.kind(), ty::ConstKind::Infer(_))
528460
}
529461
}
530-
531-
pub fn const_param_default<'tcx>(
532-
tcx: TyCtxt<'tcx>,
533-
def_id: LocalDefId,
534-
) -> ty::EarlyBinder<'tcx, Const<'tcx>> {
535-
let default_ct = match tcx.hir_node_by_def_id(def_id) {
536-
hir::Node::GenericParam(hir::GenericParam {
537-
kind: hir::GenericParamKind::Const { default: Some(ct), .. },
538-
..
539-
}) => ct,
540-
_ => span_bug!(
541-
tcx.def_span(def_id),
542-
"`const_param_default` expected a generic parameter with a constant"
543-
),
544-
};
545-
ty::EarlyBinder::bind(Const::from_const_arg(tcx, default_ct, FeedConstTy::No))
546-
}

compiler/rustc_middle/src/ty/mod.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ pub use self::closure::{
7070
place_to_string_for_capture,
7171
};
7272
pub use self::consts::{
73-
Const, ConstInt, ConstKind, Expr, ExprKind, FeedConstTy, ScalarInt, UnevaluatedConst, ValTree,
73+
Const, ConstInt, ConstKind, Expr, ExprKind, ScalarInt, UnevaluatedConst, ValTree,
7474
};
7575
pub use self::context::{
7676
CtxtInterners, CurrentGcx, DeducedParamAttrs, Feed, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt,
@@ -2119,7 +2119,6 @@ pub fn provide(providers: &mut Providers) {
21192119
incoherent_impls: trait_def::incoherent_impls_provider,
21202120
trait_impls_in_crate: trait_def::trait_impls_in_crate_provider,
21212121
traits: trait_def::traits_provider,
2122-
const_param_default: consts::const_param_default,
21232122
vtable_allocation: vtable::vtable_allocation_provider,
21242123
..*providers
21252124
};

0 commit comments

Comments
 (0)