Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit e7c85cb

Browse files
committed
Setup ty::Const functions for ConstArg
1 parent 7d7be2f commit e7c85cb

File tree

3 files changed

+86
-44
lines changed

3 files changed

+86
-44
lines changed

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -470,13 +470,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
470470
(&GenericParamDefKind::Type { has_default, .. }, GenericArg::Infer(inf)) => {
471471
handle_ty_args(has_default, &inf.to_ty())
472472
}
473-
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => match &ct.kind {
474-
hir::ConstArgKind::Anon(anon) => {
475-
let did = anon.def_id;
476-
tcx.feed_anon_const_type(did, tcx.type_of(param.def_id));
477-
ty::Const::from_anon_const(tcx, did).into()
478-
}
479-
},
473+
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
474+
ty::Const::from_const_arg(tcx, ct, ty::FeedConstTy::Param(param.def_id))
475+
.into()
476+
}
480477
(&GenericParamDefKind::Const { .. }, hir::GenericArg::Infer(inf)) => {
481478
self.lowerer.ct_infer(Some(param), inf.span).into()
482479
}

compiler/rustc_middle/src/ty/consts.rs

Lines changed: 81 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ use crate::mir::interpret::{ErrorHandled, LitToConstInput, Scalar};
33
use crate::ty::{self, GenericArgs, ParamEnv, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt};
44
use rustc_data_structures::intern::Interned;
55
use rustc_error_messages::MultiSpan;
6-
use rustc_hir as hir;
76
use rustc_hir::def::{DefKind, Res};
8-
use rustc_hir::def_id::LocalDefId;
7+
use rustc_hir::def_id::{DefId, LocalDefId};
8+
use rustc_hir::{self as hir, HirId};
99
use rustc_macros::HashStable;
1010
use rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo};
1111
use tracing::{debug, instrument};
@@ -182,16 +182,52 @@ impl<'tcx> rustc_type_ir::inherent::Const<TyCtxt<'tcx>> for Const<'tcx> {
182182
}
183183
}
184184

185+
/// In some cases, [`hir::ConstArg`]s that are being used in the type system
186+
/// through const generics need to have their type "fed" to them
187+
/// using the query system.
188+
///
189+
/// Use this enum with [`Const::from_const_arg`] to instruct it with the
190+
/// desired behavior.
191+
#[derive(Debug, Clone, Copy)]
192+
pub enum FeedConstTy {
193+
/// Feed the type.
194+
///
195+
/// The `DefId` belongs to the const param that we are supplying
196+
/// this (anon) const arg to.
197+
Param(DefId),
198+
/// Don't feed the type.
199+
No,
200+
}
201+
185202
impl<'tcx> Const<'tcx> {
203+
/// Convert a [`hir::ConstArg`] to a [`ty::Const`](Self).
204+
#[instrument(skip(tcx), level = "debug")]
205+
#[allow(irrefutable_let_patterns)]
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::Anon(anon) => Self::from_anon_const(tcx, anon.def_id),
219+
}
220+
}
221+
186222
/// Literals and const generic parameters are eagerly converted to a constant, everything else
187223
/// becomes `Unevaluated`.
188224
#[instrument(skip(tcx), level = "debug")]
189225
pub fn from_anon_const(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Self {
190226
let body_id = match tcx.hir_node_by_def_id(def) {
191227
hir::Node::AnonConst(ac) => ac.body,
192-
_ => span_bug!(
228+
node => span_bug!(
193229
tcx.def_span(def.to_def_id()),
194-
"from_anon_const can only process anonymous constants"
230+
"from_anon_const can only process anonymous constants, not {node:?}"
195231
),
196232
};
197233

@@ -200,7 +236,7 @@ impl<'tcx> Const<'tcx> {
200236

201237
let ty = tcx.type_of(def).no_bound_vars().expect("const parameter types cannot be generic");
202238

203-
match Self::try_from_lit_or_param(tcx, ty, expr) {
239+
match Self::try_from_lit(tcx, ty, expr) {
204240
Some(v) => v,
205241
None => ty::Const::new_unevaluated(
206242
tcx,
@@ -212,12 +248,36 @@ impl<'tcx> Const<'tcx> {
212248
}
213249
}
214250

251+
/// Lower a const param to a [`Const`].
252+
///
253+
/// IMPORTANT: `qpath` must be a const param, otherwise this will panic
254+
fn from_param(tcx: TyCtxt<'tcx>, qpath: hir::QPath<'tcx>, hir_id: HirId) -> Self {
255+
let hir::QPath::Resolved(_, &hir::Path { res: Res::Def(DefKind::ConstParam, def_id), .. }) =
256+
qpath
257+
else {
258+
span_bug!(qpath.span(), "non-param {qpath:?} passed to Const::from_param")
259+
};
260+
261+
match tcx.named_bound_var(hir_id) {
262+
Some(rbv::ResolvedArg::EarlyBound(_)) => {
263+
// Find the name and index of the const parameter by indexing the generics of
264+
// the parent item and construct a `ParamConst`.
265+
let item_def_id = tcx.parent(def_id);
266+
let generics = tcx.generics_of(item_def_id);
267+
let index = generics.param_def_id_to_index[&def_id];
268+
let name = tcx.item_name(def_id);
269+
ty::Const::new_param(tcx, ty::ParamConst::new(index, name))
270+
}
271+
Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => {
272+
ty::Const::new_bound(tcx, debruijn, ty::BoundVar::from_u32(index))
273+
}
274+
Some(rbv::ResolvedArg::Error(guar)) => ty::Const::new_error(tcx, guar),
275+
arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", hir_id),
276+
}
277+
}
278+
215279
#[instrument(skip(tcx), level = "debug")]
216-
fn try_from_lit_or_param(
217-
tcx: TyCtxt<'tcx>,
218-
ty: Ty<'tcx>,
219-
expr: &'tcx hir::Expr<'tcx>,
220-
) -> Option<Self> {
280+
fn try_from_lit(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, expr: &'tcx hir::Expr<'tcx>) -> Option<Self> {
221281
// Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments
222282
// currently have to be wrapped in curly brackets, so it's necessary to special-case.
223283
let expr = match &expr.kind {
@@ -250,34 +310,19 @@ impl<'tcx> Const<'tcx> {
250310
}
251311
}
252312

253-
// FIXME(const_generics): We currently have to special case parameters because `min_const_generics`
254-
// does not provide the parents generics to anonymous constants. We still allow generic const
255-
// parameters by themselves however, e.g. `N`. These constants would cause an ICE if we were to
256-
// ever try to instantiate the generic parameters in their bodies.
257-
match expr.kind {
258-
hir::ExprKind::Path(hir::QPath::Resolved(
313+
if let hir::ExprKind::Path(
314+
qpath @ hir::QPath::Resolved(
259315
_,
260-
&hir::Path { res: Res::Def(DefKind::ConstParam, def_id), .. },
261-
)) => {
262-
match tcx.named_bound_var(expr.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-
Some(ty::Const::new_param(tcx, ty::ParamConst::new(index, name)))
271-
}
272-
Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => {
273-
Some(ty::Const::new_bound(tcx, debruijn, ty::BoundVar::from_u32(index)))
274-
}
275-
Some(rbv::ResolvedArg::Error(guar)) => Some(ty::Const::new_error(tcx, guar)),
276-
arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", expr.hir_id),
277-
}
278-
}
279-
_ => None,
316+
&hir::Path { res: Res::Def(DefKind::ConstParam, _), .. },
317+
),
318+
) = expr.kind
319+
{
320+
// FIXME: once ConstArgKind::Path added, uncomment span_bug and delete return
321+
// span_bug!(expr.span, "try_from_lit: received const param which shouldn't be possible")
322+
return Some(Self::from_param(tcx, qpath, expr.hir_id));
280323
}
324+
325+
None
281326
}
282327

283328
#[inline]

compiler/rustc_middle/src/ty/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ pub use self::closure::{
8686
CAPTURE_STRUCT_LOCAL,
8787
};
8888
pub use self::consts::{
89-
Const, ConstInt, ConstKind, Expr, ExprKind, ScalarInt, UnevaluatedConst, ValTree,
89+
Const, ConstInt, ConstKind, Expr, ExprKind, FeedConstTy, ScalarInt, UnevaluatedConst, ValTree,
9090
};
9191
pub use self::context::{
9292
tls, CtxtInterners, CurrentGcx, DeducedParamAttrs, Feed, FreeRegionInfo, GlobalCtxt, Lift,

0 commit comments

Comments
 (0)