Skip to content

Commit 6ffacf1

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 4ce8126 commit 6ffacf1

File tree

9 files changed

+131
-116
lines changed

9 files changed

+131
-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
}
@@ -1777,3 +1778,22 @@ fn rendered_precise_capturing_args<'tcx>(
17771778
_ => None,
17781779
})
17791780
}
1781+
1782+
fn const_param_default<'tcx>(
1783+
tcx: TyCtxt<'tcx>,
1784+
def_id: LocalDefId,
1785+
) -> ty::EarlyBinder<'tcx, Const<'tcx>> {
1786+
let default_ct = match tcx.hir_node_by_def_id(def_id) {
1787+
hir::Node::GenericParam(hir::GenericParam {
1788+
kind: hir::GenericParamKind::Const { default: Some(ct), .. },
1789+
..
1790+
}) => ct,
1791+
_ => span_bug!(
1792+
tcx.def_span(def_id),
1793+
"`const_param_default` expected a generic parameter with a constant"
1794+
),
1795+
};
1796+
let icx = ItemCtxt::new(tcx, def_id);
1797+
let ct = icx.lowerer().lower_const_arg(default_ct, FeedConstTy::No);
1798+
ty::EarlyBinder::bind(ct)
1799+
}

compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ use tracing::{debug, instrument};
1919
use super::errors::GenericsArgsErrExtend;
2020
use crate::bounds::Bounds;
2121
use crate::errors;
22-
use crate::hir_ty_lowering::{AssocItemQSelf, HirTyLowerer, PredicateFilter, RegionInferReason};
22+
use crate::hir_ty_lowering::{
23+
AssocItemQSelf, FeedConstTy, HirTyLowerer, PredicateFilter, RegionInferReason,
24+
};
2325

2426
impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
2527
/// Add a `Sized` bound to the `bounds` if appropriate.
@@ -383,9 +385,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
383385
hir::AssocItemConstraintKind::Equality { term } => {
384386
let term = match term {
385387
hir::Term::Ty(ty) => self.lower_ty(ty).into(),
386-
hir::Term::Const(ct) => {
387-
ty::Const::from_const_arg(tcx, ct, ty::FeedConstTy::No).into()
388-
}
388+
hir::Term::Const(ct) => self.lower_const_arg(ct, FeedConstTy::No).into(),
389389
};
390390

391391
// 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
@@ -211,6 +211,23 @@ impl AssocItemQSelf {
211211
}
212212
}
213213

214+
/// In some cases, [`hir::ConstArg`]s that are being used in the type system
215+
/// through const generics need to have their type "fed" to them
216+
/// using the query system.
217+
///
218+
/// Use this enum with [`Const::from_const_arg`] to instruct it with the
219+
/// desired behavior.
220+
#[derive(Debug, Clone, Copy)]
221+
pub enum FeedConstTy {
222+
/// Feed the type.
223+
///
224+
/// The `DefId` belongs to the const param that we are supplying
225+
/// this (anon) const arg to.
226+
Param(DefId),
227+
/// Don't feed the type.
228+
No,
229+
}
230+
214231
/// New-typed boolean indicating whether explicit late-bound lifetimes
215232
/// are present in a set of generic arguments.
216233
///
@@ -486,8 +503,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
486503
handle_ty_args(has_default, &inf.to_ty())
487504
}
488505
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
489-
ty::Const::from_const_arg(tcx, ct, ty::FeedConstTy::Param(param.def_id))
490-
.into()
506+
self.lowerer.lower_const_arg(ct, FeedConstTy::Param(param.def_id)).into()
491507
}
492508
(&GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => {
493509
self.lowerer.ct_infer(Some(param), inf.span).into()
@@ -904,8 +920,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
904920
let term: ty::Term<'_> = match term {
905921
hir::Term::Ty(ty) => self.lower_ty(ty).into(),
906922
hir::Term::Const(ct) => {
907-
ty::Const::from_const_arg(tcx, ct, ty::FeedConstTy::No)
908-
.into()
923+
self.lower_const_arg(ct, FeedConstTy::No).into()
909924
}
910925
};
911926
// FIXME(#97583): This isn't syntactically well-formed!
@@ -1979,6 +1994,60 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
19791994
}
19801995
}
19811996

1997+
/// Convert a [`hir::ConstArg`] to a [`ty::Const`](Const).
1998+
#[instrument(skip(self), level = "debug")]
1999+
pub fn lower_const_arg(
2000+
&self,
2001+
const_arg: &hir::ConstArg<'tcx>,
2002+
feed: FeedConstTy,
2003+
) -> Const<'tcx> {
2004+
let tcx = self.tcx();
2005+
2006+
if let FeedConstTy::Param(param_def_id) = feed
2007+
&& let hir::ConstArgKind::Anon(anon) = &const_arg.kind
2008+
{
2009+
tcx.feed_anon_const_type(anon.def_id, tcx.type_of(param_def_id));
2010+
}
2011+
2012+
match const_arg.kind {
2013+
hir::ConstArgKind::Path(qpath) => {
2014+
// FIXME(min_generic_const_args): for now only params are lowered to ConstArgKind::Path
2015+
self.lower_const_arg_param(qpath, const_arg.hir_id)
2016+
}
2017+
hir::ConstArgKind::Anon(anon) => Const::from_anon_const(tcx, anon.def_id),
2018+
}
2019+
}
2020+
2021+
/// Lower a use of a const param to a [`Const`].
2022+
///
2023+
/// IMPORTANT: `qpath` must be a const param, otherwise this will panic
2024+
fn lower_const_arg_param(&self, qpath: hir::QPath<'tcx>, hir_id: HirId) -> Const<'tcx> {
2025+
let tcx = self.tcx();
2026+
2027+
let hir::QPath::Resolved(_, &hir::Path { res: Res::Def(DefKind::ConstParam, def_id), .. }) =
2028+
qpath
2029+
else {
2030+
span_bug!(qpath.span(), "non-param {qpath:?} passed to Const::from_param")
2031+
};
2032+
2033+
match tcx.named_bound_var(hir_id) {
2034+
Some(rbv::ResolvedArg::EarlyBound(_)) => {
2035+
// Find the name and index of the const parameter by indexing the generics of
2036+
// the parent item and construct a `ParamConst`.
2037+
let item_def_id = tcx.parent(def_id);
2038+
let generics = tcx.generics_of(item_def_id);
2039+
let index = generics.param_def_id_to_index[&def_id];
2040+
let name = tcx.item_name(def_id);
2041+
ty::Const::new_param(tcx, ty::ParamConst::new(index, name))
2042+
}
2043+
Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => {
2044+
ty::Const::new_bound(tcx, debruijn, ty::BoundVar::from_u32(index))
2045+
}
2046+
Some(rbv::ResolvedArg::Error(guar)) => ty::Const::new_error(tcx, guar),
2047+
arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", hir_id),
2048+
}
2049+
}
2050+
19822051
fn lower_delegation_ty(&self, idx: hir::InferDelegationKind) -> Ty<'tcx> {
19832052
let delegation_sig = self.tcx().inherit_sig_for_delegation_item(self.item_def_id());
19842053
match idx {
@@ -2122,7 +2191,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
21222191
let length = match length {
21232192
hir::ArrayLen::Infer(inf) => self.ct_infer(None, inf.span),
21242193
hir::ArrayLen::Body(constant) => {
2125-
ty::Const::from_const_arg(tcx, constant, ty::FeedConstTy::No)
2194+
self.lower_const_arg(constant, FeedConstTy::No)
21262195
}
21272196
};
21282197

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};
@@ -469,7 +469,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
469469
hir::ArrayLen::Infer(inf) => self.ct_infer(None, inf.span),
470470
hir::ArrayLen::Body(const_arg) => {
471471
let span = const_arg.span();
472-
let c = ty::Const::from_const_arg(self.tcx, const_arg, ty::FeedConstTy::No);
472+
let c = self.lowerer().lower_const_arg(const_arg, FeedConstTy::No);
473473
self.register_wf_obligation(c.into(), span, ObligationCauseCode::WellFormed(None));
474474
self.normalize(span, c)
475475
}
@@ -481,8 +481,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
481481
const_arg: &'tcx hir::ConstArg<'tcx>,
482482
param_def_id: DefId,
483483
) -> ty::Const<'tcx> {
484-
let ct =
485-
ty::Const::from_const_arg(self.tcx, const_arg, ty::FeedConstTy::Param(param_def_id));
484+
let ct = self.lowerer().lower_const_arg(const_arg, FeedConstTy::Param(param_def_id));
486485
self.register_wf_obligation(
487486
ct.into(),
488487
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,
@@ -2101,7 +2101,6 @@ pub fn provide(providers: &mut Providers) {
21012101
incoherent_impls: trait_def::incoherent_impls_provider,
21022102
trait_impls_in_crate: trait_def::trait_impls_in_crate_provider,
21032103
traits: trait_def::traits_provider,
2104-
const_param_default: consts::const_param_default,
21052104
vtable_allocation: vtable::vtable_allocation_provider,
21062105
..*providers
21072106
};

0 commit comments

Comments
 (0)