Skip to content

Commit 603f391

Browse files
committed
impl astconv for ConstArgKind
1 parent 6946282 commit 603f391

File tree

6 files changed

+152
-76
lines changed

6 files changed

+152
-76
lines changed

compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2393,6 +2393,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
23932393
}
23942394

23952395
fn lower_array_length(&mut self, c: &AnonConst) -> hir::ArrayLen {
2396+
// FIXME(const_arg_kind)
23962397
match c.value.kind {
23972398
ExprKind::Underscore => {
23982399
if self.tcx.features().generic_arg_infer {

compiler/rustc_hir/src/hir.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,13 @@ impl<'hir> ConstArg<'hir> {
259259
ConstArgKind::Param(_, qpath) => qpath.span(),
260260
}
261261
}
262+
263+
pub fn hir_id(&self) -> HirId {
264+
match self.kind {
265+
ConstArgKind::AnonConst(_, ct) => ct.hir_id,
266+
ConstArgKind::Param(id, _) => id,
267+
}
268+
}
262269
}
263270

264271
#[derive(Clone, Copy, Debug, HashStable_Generic)]
@@ -295,10 +302,7 @@ impl GenericArg<'_> {
295302
match self {
296303
GenericArg::Lifetime(l) => l.hir_id,
297304
GenericArg::Type(t) => t.hir_id,
298-
GenericArg::Const(c) => match c.kind {
299-
ConstArgKind::AnonConst(_, ct) => ct.hir_id,
300-
ConstArgKind::Param(id, _) => id,
301-
},
305+
GenericArg::Const(c) => c.hir_id(),
302306
GenericArg::Infer(i) => i.hir_id,
303307
}
304308
}

compiler/rustc_hir_analysis/src/astconv/generics.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -108,16 +108,14 @@ fn generic_arg_mismatch_err(
108108
}
109109
}
110110
(GenericArg::Const(cnst), GenericParamDefKind::Type { .. })
111-
if matches!(cnst.kind, hir::ConstArgKind::AnonConst(_, _)) =>
111+
if matches!(cnst.kind, hir::ConstArgKind::Param(_, _)) =>
112112
{
113-
// FIXME(const_arg_kind)
114-
let body = match cnst.kind {
115-
hir::ConstArgKind::AnonConst(_, cnst) => tcx.hir().body(cnst.body),
113+
let path = match cnst.kind {
114+
hir::ConstArgKind::Param(_, path) => path,
116115
_ => unreachable!(),
117116
};
118117

119-
if let rustc_hir::ExprKind::Path(rustc_hir::QPath::Resolved(_, path)) = body.value.kind
120-
{
118+
if let rustc_hir::QPath::Resolved(_, path) = path {
121119
if let Res::Def(DefKind::Fn { .. }, id) = path.res {
122120
err.help(format!("`{}` is a function item, not a type", tcx.item_name(id)));
123121
err.help("function item types cannot be named directly");

compiler/rustc_hir_analysis/src/astconv/mod.rs

Lines changed: 130 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use crate::errors::{
1515
};
1616
use crate::middle::resolve_bound_vars as rbv;
1717
use crate::require_c_abi_if_c_variadic;
18+
use hir::def::CtorKind;
1819
use rustc_ast::TraitObjectSyntax;
1920
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
2021
use rustc_errors::{
@@ -34,7 +35,9 @@ use rustc_middle::middle::stability::AllowUnstable;
3435
use rustc_middle::ty::fold::FnMutDelegate;
3536
use rustc_middle::ty::subst::{self, GenericArgKind, InternalSubsts, SubstsRef};
3637
use rustc_middle::ty::GenericParamDefKind;
37-
use rustc_middle::ty::{self, Const, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
38+
use rustc_middle::ty::{
39+
self, Const, IsSuggestable, Ty, TyCtxt, TypeVisitableExt, UnevaluatedConst,
40+
};
3841
use rustc_middle::ty::{DynKind, ToPredicate};
3942
use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, BARE_TRAIT_OBJECTS};
4043
use rustc_span::edit_distance::find_best_match_for_name;
@@ -449,15 +452,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
449452
(&GenericParamDefKind::Type { has_default, .. }, GenericArg::Infer(inf)) => {
450453
handle_ty_args(has_default, &inf.to_ty())
451454
}
452-
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => match ct.kind {
453-
// FIXME(const_arg_kind)
454-
hir::ConstArgKind::AnonConst(_, ct) => {
455-
let did = ct.def_id;
456-
tcx.feed_anon_const_type(did, tcx.type_of(param.def_id));
457-
ty::Const::from_anon_const(tcx, did).into()
458-
}
459-
hir::ConstArgKind::Param(_, _) => todo!(),
460-
},
455+
(GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => {
456+
self.astconv.ast_const_to_const(ct, param.def_id).into()
457+
}
461458
(&GenericParamDefKind::Const { .. }, hir::GenericArg::Infer(inf)) => {
462459
let ty = tcx
463460
.at(self.span)
@@ -3757,6 +3754,129 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
37573754
}
37583755
}
37593756
}
3757+
3758+
#[instrument(level = "debug", skip(self), ret)]
3759+
pub fn ast_const_to_const(
3760+
&self,
3761+
ast_ct: &hir::ConstArg<'_>,
3762+
param_def_id: DefId,
3763+
) -> Const<'tcx> {
3764+
let tcx = self.tcx();
3765+
3766+
match ast_ct.kind {
3767+
hir::ConstArgKind::AnonConst(_, ct) => {
3768+
tcx.feed_anon_const_type(ct.def_id, tcx.type_of(param_def_id));
3769+
Const::from_anon_const(tcx, ct.def_id)
3770+
}
3771+
hir::ConstArgKind::Param(_, path) => match path {
3772+
hir::QPath::Resolved(_, path) => match path.res {
3773+
Res::Def(def_kind, def_id) => match def_kind {
3774+
DefKind::ConstParam => {
3775+
self.prohibit_generics(path.segments.iter(), |_| {});
3776+
let param_ty = tcx.type_of(def_id).subst_identity();
3777+
3778+
match tcx.named_bound_var(ast_ct.hir_id()) {
3779+
Some(rbv::ResolvedArg::EarlyBound(_)) => {
3780+
// Find the name and index of the const parameter by indexing the generics of
3781+
// the parent item and construct a `ParamConst`.
3782+
let item_def_id = tcx.parent(def_id);
3783+
let generics = tcx.generics_of(item_def_id);
3784+
let index = generics.param_def_id_to_index[&def_id];
3785+
let name = tcx.item_name(def_id);
3786+
tcx.mk_const(ty::ParamConst::new(index, name), param_ty)
3787+
}
3788+
Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => tcx
3789+
.mk_const(
3790+
ty::ConstKind::Bound(
3791+
debruijn,
3792+
ty::BoundVar::from_u32(index),
3793+
),
3794+
param_ty,
3795+
),
3796+
Some(rbv::ResolvedArg::Error(guar)) => {
3797+
tcx.const_error_with_guaranteed(param_ty, guar)
3798+
}
3799+
arg => bug!(
3800+
"unexpected bound var resolution for {:?}: {arg:?}",
3801+
ast_ct.hir_id()
3802+
),
3803+
}
3804+
}
3805+
DefKind::Const => {
3806+
let (last, prev) = path.segments.split_last().unwrap();
3807+
self.prohibit_generics(prev.iter(), |_| {});
3808+
let substs = self.ast_path_substs_for_ty(ast_ct.span(), def_id, last);
3809+
tcx.mk_const(
3810+
UnevaluatedConst { def: def_id, substs },
3811+
tcx.type_of(def_id).subst(tcx, substs),
3812+
)
3813+
}
3814+
3815+
DefKind::Ctor(_, _) => todo!(),
3816+
DefKind::Fn => todo!(),
3817+
3818+
DefKind::AssocFn | DefKind::AssocConst => {
3819+
unimplemented!("multi segment paths are not supported")
3820+
}
3821+
3822+
// FIXME(const_arg_kind): somewhere else should be emitting this
3823+
DefKind::Static(_) => {
3824+
let e = tcx
3825+
.sess
3826+
.span_err(ast_ct.span(), "no static access in consts allowed");
3827+
tcx.const_error_with_guaranteed(tcx.ty_error(e), e)
3828+
}
3829+
3830+
DefKind::OpaqueTy
3831+
| DefKind::InlineConst
3832+
| DefKind::ForeignMod
3833+
| DefKind::AnonConst
3834+
| DefKind::Macro(_)
3835+
| DefKind::ExternCrate
3836+
| DefKind::Use
3837+
| DefKind::LifetimeParam
3838+
| DefKind::Struct
3839+
| DefKind::Union
3840+
| DefKind::Enum
3841+
| DefKind::Variant
3842+
| DefKind::Trait
3843+
| DefKind::TyAlias
3844+
| DefKind::ForeignTy
3845+
| DefKind::TraitAlias
3846+
| DefKind::AssocTy
3847+
| DefKind::TyParam
3848+
| DefKind::ImplTraitPlaceholder
3849+
| DefKind::Field
3850+
| DefKind::GlobalAsm
3851+
| DefKind::Impl { .. }
3852+
| DefKind::Closure
3853+
| DefKind::Mod
3854+
| DefKind::Generator => bug!("unexpected path res of const arg"),
3855+
},
3856+
3857+
Res::SelfCtor(_) => todo!(),
3858+
3859+
Res::Err
3860+
| Res::Local(_)
3861+
| Res::ToolMod
3862+
| Res::NonMacroAttr(_)
3863+
| Res::PrimTy(_)
3864+
| Res::SelfTyParam { .. }
3865+
| Res::SelfTyAlias { .. } => {
3866+
let e = tcx.sess.delay_span_bug(
3867+
ast_ct.span(),
3868+
format!("unexpected path res {:?} of const arg {:?}", path.res, ast_ct),
3869+
);
3870+
tcx.const_error_with_guaranteed(tcx.ty_error(e), e)
3871+
}
3872+
},
3873+
hir::QPath::TypeRelative(_, _) => {
3874+
bug!("multi-segment path consts are not yet supported")
3875+
}
3876+
hir::QPath::LangItem(_, _, _) => unimplemented!(),
3877+
},
3878+
}
3879+
}
37603880
}
37613881

37623882
pub trait InferCtxtExt<'tcx> {

compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
404404
}
405405

406406
pub fn array_length_to_const(&self, length: &hir::ArrayLen) -> ty::Const<'tcx> {
407+
// FIXME(const_arg_kind)
407408
match length {
408409
&hir::ArrayLen::Infer(_, span) => self.ct_infer(self.tcx.types.usize, None, span),
409410
hir::ArrayLen::Body(anon_const) => {
@@ -420,21 +421,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
420421
ast_c: &hir::ConstArg<'_>,
421422
param_def_id: DefId,
422423
) -> ty::Const<'tcx> {
423-
// FIXME(const_arg_kind)
424-
match ast_c.kind {
425-
hir::ConstArgKind::AnonConst(_, ast_c) => {
426-
let did = ast_c.def_id;
427-
self.tcx.feed_anon_const_type(did, self.tcx.type_of(param_def_id));
428-
let c = ty::Const::from_anon_const(self.tcx, did);
429-
self.register_wf_obligation(
430-
c.into(),
431-
self.tcx.hir().span(ast_c.hir_id),
432-
ObligationCauseCode::WellFormed(None),
433-
);
434-
c
435-
}
436-
hir::ConstArgKind::Param(_, _) => todo!(),
437-
}
424+
let ct = self.astconv().ast_const_to_const(ast_c, param_def_id);
425+
self.register_wf_obligation(ct.into(), ast_c.span(), ObligationCauseCode::WellFormed(None));
426+
ct
438427
}
439428

440429
// If the type given by the user has free regions, save it for later, since

compiler/rustc_middle/src/ty/consts.rs

Lines changed: 5 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
1-
use crate::middle::resolve_bound_vars as rbv;
21
use crate::mir::interpret::LitToConstInput;
32
use crate::ty::{self, InternalSubsts, ParamEnv, ParamEnvAnd, Ty, TyCtxt};
43
use rustc_data_structures::intern::Interned;
54
use rustc_hir as hir;
6-
use rustc_hir::def::{DefKind, Res};
75
use rustc_hir::def_id::LocalDefId;
86
use rustc_macros::HashStable;
97
use std::fmt;
@@ -51,7 +49,7 @@ impl<'tcx> Const<'tcx> {
5149
self.0.kind
5250
}
5351

54-
/// Literals and const generic parameters are eagerly converted to a constant, everything else
52+
/// Literals are eagerly converted to a constant, everything else
5553
/// becomes `Unevaluated`.
5654
#[instrument(skip(tcx), level = "debug")]
5755
pub fn from_anon_const(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Self {
@@ -68,7 +66,7 @@ impl<'tcx> Const<'tcx> {
6866

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

71-
match Self::try_eval_lit_or_param(tcx, ty, expr) {
69+
match Self::try_eval_lit(tcx, ty, expr) {
7270
Some(v) => v,
7371
None => tcx.mk_const(
7472
ty::UnevaluatedConst {
@@ -81,12 +79,8 @@ impl<'tcx> Const<'tcx> {
8179
}
8280

8381
#[instrument(skip(tcx), level = "debug")]
84-
fn try_eval_lit_or_param(
85-
tcx: TyCtxt<'tcx>,
86-
ty: Ty<'tcx>,
87-
expr: &'tcx hir::Expr<'tcx>,
88-
) -> Option<Self> {
89-
// Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments
82+
fn try_eval_lit(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, expr: &'tcx hir::Expr<'tcx>) -> Option<Self> {
83+
// Unwrap a block, so that e.g. `{ 1 }` is recognised as a literal. Const arguments
9084
// currently have to be wrapped in curly brackets, so it's necessary to special-case.
9185
let expr = match &expr.kind {
9286
hir::ExprKind::Block(block, _) if block.stmts.is_empty() && block.expr.is_some() => {
@@ -119,37 +113,7 @@ impl<'tcx> Const<'tcx> {
119113
}
120114
}
121115
}
122-
123-
match expr.kind {
124-
hir::ExprKind::Path(hir::QPath::Resolved(
125-
_,
126-
&hir::Path { res: Res::Def(DefKind::ConstParam, def_id), .. },
127-
)) => {
128-
// Use the type from the param's definition, since we can resolve it,
129-
// not the expected parameter type from WithOptConstParam.
130-
let param_ty = tcx.type_of(def_id).subst_identity();
131-
match tcx.named_bound_var(expr.hir_id) {
132-
Some(rbv::ResolvedArg::EarlyBound(_)) => {
133-
// Find the name and index of the const parameter by indexing the generics of
134-
// the parent item and construct a `ParamConst`.
135-
let item_def_id = tcx.parent(def_id);
136-
let generics = tcx.generics_of(item_def_id);
137-
let index = generics.param_def_id_to_index[&def_id];
138-
let name = tcx.item_name(def_id);
139-
Some(tcx.mk_const(ty::ParamConst::new(index, name), param_ty))
140-
}
141-
Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => Some(tcx.mk_const(
142-
ty::ConstKind::Bound(debruijn, ty::BoundVar::from_u32(index)),
143-
param_ty,
144-
)),
145-
Some(rbv::ResolvedArg::Error(guar)) => {
146-
Some(tcx.const_error_with_guaranteed(param_ty, guar))
147-
}
148-
arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", expr.hir_id),
149-
}
150-
}
151-
_ => None,
152-
}
116+
None
153117
}
154118

155119
/// Panics if self.kind != ty::ConstKind::Value

0 commit comments

Comments
 (0)