Skip to content

Commit b0698b4

Browse files
committed
MGCA: Support tuple expressions as direct const arguments
1 parent b7bcaa5 commit b0698b4

15 files changed

Lines changed: 172 additions & 27 deletions

File tree

compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2425,6 +2425,23 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
24252425
kind: hir::ConstArgKind::TupleCall(qpath, lowered_args),
24262426
}
24272427
}
2428+
ExprKind::Tup(exprs) => {
2429+
let exprs = self.arena.alloc_from_iter(exprs.iter().map(|expr| {
2430+
let expr = if let ExprKind::ConstBlock(anon_const) = &expr.kind {
2431+
let def_id = self.local_def_id(anon_const.id);
2432+
let def_kind = self.tcx.def_kind(def_id);
2433+
assert_eq!(DefKind::AnonConst, def_kind);
2434+
2435+
self.lower_anon_const_to_const_arg_direct(anon_const)
2436+
} else {
2437+
self.lower_expr_to_const_arg_direct(&expr)
2438+
};
2439+
2440+
&*self.arena.alloc(expr)
2441+
}));
2442+
2443+
ConstArg { hir_id: self.next_id(), kind: hir::ConstArgKind::Tup(expr.span, exprs) }
2444+
}
24282445
ExprKind::Path(qself, path) => {
24292446
let qpath = self.lower_qpath(
24302447
expr.id,
@@ -2493,6 +2510,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
24932510
| ExprKind::Path(..)
24942511
| ExprKind::Struct(..)
24952512
| ExprKind::Call(..)
2513+
| ExprKind::Tup(..)
24962514
)
24972515
{
24982516
return self.lower_expr_to_const_arg_direct(expr);

compiler/rustc_hir/src/hir.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,7 @@ impl<'hir, Unambig> ConstArg<'hir, Unambig> {
497497

498498
pub fn span(&self) -> Span {
499499
match self.kind {
500+
ConstArgKind::Tup(span, ..) => span,
500501
ConstArgKind::Struct(path, _) => path.span(),
501502
ConstArgKind::Path(path) => path.span(),
502503
ConstArgKind::TupleCall(path, _) => path.span(),
@@ -511,6 +512,7 @@ impl<'hir, Unambig> ConstArg<'hir, Unambig> {
511512
#[derive(Clone, Copy, Debug, HashStable_Generic)]
512513
#[repr(u8, C)]
513514
pub enum ConstArgKind<'hir, Unambig = ()> {
515+
Tup(Span, &'hir [&'hir ConstArg<'hir, Unambig>]),
514516
/// **Note:** Currently this is only used for bare const params
515517
/// (`N` where `fn foo<const N: usize>(...)`),
516518
/// not paths to any const (`N` where `const N: usize = ...`).

compiler/rustc_hir/src/intravisit.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1081,6 +1081,10 @@ pub fn walk_const_arg<'v, V: Visitor<'v>>(
10811081
let ConstArg { hir_id, kind } = const_arg;
10821082
try_visit!(visitor.visit_id(*hir_id));
10831083
match kind {
1084+
ConstArgKind::Tup(_, exprs) => {
1085+
walk_list!(visitor, visit_const_arg, *exprs);
1086+
V::Result::output()
1087+
}
10841088
ConstArgKind::Struct(qpath, field_exprs) => {
10851089
try_visit!(visitor.visit_qpath(qpath, *hir_id, qpath.span()));
10861090

compiler/rustc_hir_analysis/src/collect.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1493,9 +1493,10 @@ fn const_param_default<'tcx>(
14931493
};
14941494
let icx = ItemCtxt::new(tcx, def_id);
14951495
let identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
1496-
let ct = icx
1497-
.lowerer()
1498-
.lower_const_arg(default_ct, FeedConstTy::Param(def_id.to_def_id(), identity_args));
1496+
let ct = icx.lowerer().lower_const_arg(
1497+
default_ct,
1498+
FeedConstTy::with_type_of(tcx, def_id.to_def_id(), identity_args),
1499+
);
14991500
ty::EarlyBinder::bind(ct)
15001501
}
15011502

@@ -1553,7 +1554,7 @@ fn const_of_item<'tcx>(
15531554
let identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
15541555
let ct = icx
15551556
.lowerer()
1556-
.lower_const_arg(ct_arg, FeedConstTy::Param(def_id.to_def_id(), identity_args));
1557+
.lower_const_arg(ct_arg, FeedConstTy::with_type_of(tcx, def_id.to_def_id(), identity_args));
15571558
if let Err(e) = icx.check_tainted_by_errors()
15581559
&& !ct.references_error()
15591560
{

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

Lines changed: 51 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -259,17 +259,26 @@ impl AssocItemQSelf {
259259
/// Use this enum with `<dyn HirTyLowerer>::lower_const_arg` to instruct it with the
260260
/// desired behavior.
261261
#[derive(Debug, Clone, Copy)]
262-
pub enum FeedConstTy<'a, 'tcx> {
263-
/// Feed the type.
264-
///
262+
pub enum FeedConstTy<'tcx> {
263+
/// Feed the type to the (anno) const arg.
264+
WithTy(Ty<'tcx>),
265+
/// Don't feed the type.
266+
No,
267+
}
268+
269+
impl<'tcx> FeedConstTy<'tcx> {
265270
/// The `DefId` belongs to the const param that we are supplying
266271
/// this (anon) const arg to.
267272
///
268273
/// The list of generic args is used to instantiate the parameters
269274
/// used by the type of the const param specified by `DefId`.
270-
Param(DefId, &'a [ty::GenericArg<'tcx>]),
271-
/// Don't feed the type.
272-
No,
275+
pub fn with_type_of(
276+
tcx: TyCtxt<'tcx>,
277+
def_id: DefId,
278+
generic_args: &[ty::GenericArg<'tcx>],
279+
) -> Self {
280+
Self::WithTy(tcx.type_of(def_id).instantiate(tcx, generic_args))
281+
}
273282
}
274283

275284
#[derive(Debug, Clone, Copy)]
@@ -723,7 +732,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
723732
// Ambig portions of `ConstArg` are handled in the match arm below
724733
.lower_const_arg(
725734
ct.as_unambig_ct(),
726-
FeedConstTy::Param(param.def_id, preceding_args),
735+
FeedConstTy::with_type_of(tcx, param.def_id, preceding_args),
727736
)
728737
.into(),
729738
(&GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => {
@@ -2297,15 +2306,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
22972306
pub fn lower_const_arg(
22982307
&self,
22992308
const_arg: &hir::ConstArg<'tcx>,
2300-
feed: FeedConstTy<'_, 'tcx>,
2309+
feed: FeedConstTy<'tcx>,
23012310
) -> Const<'tcx> {
23022311
let tcx = self.tcx();
23032312

2304-
if let FeedConstTy::Param(param_def_id, args) = feed
2313+
if let FeedConstTy::WithTy(anon_const_type) = feed
23052314
&& let hir::ConstArgKind::Anon(anon) = &const_arg.kind
23062315
{
2307-
let anon_const_type = tcx.type_of(param_def_id).instantiate(tcx, args);
2308-
23092316
// FIXME(generic_const_parameter_types): Ideally we remove these errors below when
23102317
// we have the ability to intermix typeck of anon const const args with the parent
23112318
// bodies typeck.
@@ -2346,14 +2353,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
23462353
return ty::Const::new_error(tcx, e);
23472354
}
23482355

2349-
tcx.feed_anon_const_type(
2350-
anon.def_id,
2351-
ty::EarlyBinder::bind(tcx.type_of(param_def_id).instantiate(tcx, args)),
2352-
);
2356+
tcx.feed_anon_const_type(anon.def_id, ty::EarlyBinder::bind(anon_const_type));
23532357
}
23542358

23552359
let hir_id = const_arg.hir_id;
23562360
match const_arg.kind {
2361+
hir::ConstArgKind::Tup(span, exprs) => self.lower_const_arg_tup(exprs, feed, span),
23572362
hir::ConstArgKind::Path(hir::QPath::Resolved(maybe_qself, path)) => {
23582363
debug!(?maybe_qself, ?path);
23592364
let opt_self_ty = maybe_qself.as_ref().map(|qself| self.lower_ty(qself));
@@ -2458,7 +2463,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
24582463
.iter()
24592464
.zip(args)
24602465
.map(|(field_def, arg)| {
2461-
self.lower_const_arg(arg, FeedConstTy::Param(field_def.did, adt_args))
2466+
self.lower_const_arg(arg, FeedConstTy::with_type_of(tcx, field_def.did, adt_args))
24622467
})
24632468
.collect::<Vec<_>>();
24642469

@@ -2474,6 +2479,32 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
24742479
ty::Const::new_value(tcx, valtree, adt_ty)
24752480
}
24762481

2482+
fn lower_const_arg_tup(
2483+
&self,
2484+
exprs: &'tcx [&'tcx hir::ConstArg<'tcx>],
2485+
feed: FeedConstTy<'tcx>,
2486+
span: Span,
2487+
) -> Const<'tcx> {
2488+
let tcx = self.tcx();
2489+
2490+
let FeedConstTy::WithTy(ty) = feed else {
2491+
return Const::new_error_with_message(tcx, span, "unsupported const tuple");
2492+
};
2493+
2494+
let ty::Tuple(tys) = ty.kind() else {
2495+
return Const::new_error_with_message(tcx, span, "const tuple must have a tuple type");
2496+
};
2497+
2498+
let exprs = exprs
2499+
.iter()
2500+
.zip(tys.iter())
2501+
.map(|(expr, ty)| self.lower_const_arg(expr, FeedConstTy::WithTy(ty)))
2502+
.collect::<Vec<_>>();
2503+
2504+
let valtree = ty::ValTree::from_branches(tcx, exprs);
2505+
ty::Const::new_value(tcx, valtree, ty)
2506+
}
2507+
24772508
fn lower_const_arg_struct(
24782509
&self,
24792510
hir_id: HirId,
@@ -2552,7 +2583,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
25522583
return ty::Const::new_error(tcx, e);
25532584
}
25542585

2555-
self.lower_const_arg(expr.expr, FeedConstTy::Param(field_def.did, adt_args))
2586+
self.lower_const_arg(
2587+
expr.expr,
2588+
FeedConstTy::with_type_of(tcx, field_def.did, adt_args),
2589+
)
25562590
}
25572591
None => {
25582592
let e = tcx.dcx().span_err(

compiler/rustc_hir_analysis/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ pub fn lower_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
301301
pub fn lower_const_arg_for_rustdoc<'tcx>(
302302
tcx: TyCtxt<'tcx>,
303303
hir_ct: &hir::ConstArg<'tcx>,
304-
feed: FeedConstTy<'_, 'tcx>,
304+
feed: FeedConstTy<'tcx>,
305305
) -> Const<'tcx> {
306306
let env_def_id = tcx.hir_get_parent_item(hir_ct.hir_id);
307307
collect::ItemCtxt::new(tcx, env_def_id.def_id).lowerer().lower_const_arg(hir_ct, feed)

compiler/rustc_hir_pretty/src/lib.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1137,6 +1137,16 @@ impl<'a> State<'a> {
11371137

11381138
fn print_const_arg(&mut self, const_arg: &hir::ConstArg<'_>) {
11391139
match &const_arg.kind {
1140+
ConstArgKind::Tup(_, exprs) => {
1141+
self.popen();
1142+
self.commasep_cmnt(
1143+
Inconsistent,
1144+
exprs,
1145+
|s, arg| s.print_const_arg(arg),
1146+
|arg| arg.span(),
1147+
);
1148+
self.pclose();
1149+
}
11401150
// FIXME(mgca): proper printing for struct exprs
11411151
ConstArgKind::Struct(..) => self.word("/* STRUCT EXPR */"),
11421152
ConstArgKind::TupleCall(..) => self.word("/* TUPLE CALL */"),

compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
525525
pub(crate) fn lower_const_arg(
526526
&self,
527527
const_arg: &'tcx hir::ConstArg<'tcx>,
528-
feed: FeedConstTy<'_, 'tcx>,
528+
feed: FeedConstTy<'tcx>,
529529
) -> ty::Const<'tcx> {
530530
let ct = self.lowerer().lower_const_arg(const_arg, feed);
531531
self.register_wf_obligation(
@@ -1228,7 +1228,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12281228
// Ambiguous parts of `ConstArg` are handled in the match arms below
12291229
.lower_const_arg(
12301230
ct.as_unambig_ct(),
1231-
FeedConstTy::Param(param.def_id, preceding_args),
1231+
FeedConstTy::with_type_of(self.fcx.tcx, param.def_id, preceding_args),
12321232
)
12331233
.into(),
12341234
(&GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => {

compiler/rustc_hir_typeck/src/method/confirm.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -447,7 +447,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
447447
// We handle the ambig portions of `ConstArg` in the match arms below
448448
.lower_const_arg(
449449
ct.as_unambig_ct(),
450-
FeedConstTy::Param(param.def_id, preceding_args),
450+
FeedConstTy::with_type_of(self.cfcx.tcx, param.def_id, preceding_args),
451451
)
452452
.into(),
453453
(GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => {

compiler/rustc_metadata/src/rmeta/encoder.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1442,6 +1442,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
14421442
hir::ConstArgKind::Error(..)
14431443
| hir::ConstArgKind::Struct(..)
14441444
| hir::ConstArgKind::TupleCall(..)
1445+
| hir::ConstArgKind::Tup(..)
14451446
| hir::ConstArgKind::Path(..)
14461447
| hir::ConstArgKind::Infer(..) => true,
14471448
hir::ConstArgKind::Anon(..) => false,

0 commit comments

Comments
 (0)