Skip to content

Commit a786e30

Browse files
committed
Syntactically distinguish anon const const args
1 parent 07bdbae commit a786e30

File tree

71 files changed

+753
-310
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+753
-310
lines changed

compiler/rustc_ast/src/ast.rs

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -141,16 +141,11 @@ impl Path {
141141
/// Check if this path is potentially a trivial const arg, i.e., one that can _potentially_
142142
/// be represented without an anon const in the HIR.
143143
///
144-
/// If `allow_mgca_arg` is true (as should be the case in most situations when
145-
/// `#![feature(min_generic_const_args)]` is enabled), then this always returns true
146-
/// because all paths are valid.
147-
///
148-
/// Otherwise, it returns true iff the path has exactly one segment, and it has no generic args
144+
/// Returns true iff the path has exactly one segment, and it has no generic args
149145
/// (i.e., it is _potentially_ a const parameter).
150146
#[tracing::instrument(level = "debug", ret)]
151-
pub fn is_potential_trivial_const_arg(&self, allow_mgca_arg: bool) -> bool {
152-
allow_mgca_arg
153-
|| self.segments.len() == 1 && self.segments.iter().all(|seg| seg.args.is_none())
147+
pub fn is_potential_trivial_const_arg(&self) -> bool {
148+
self.segments.len() == 1 && self.segments.iter().all(|seg| seg.args.is_none())
154149
}
155150
}
156151

@@ -1372,6 +1367,15 @@ pub enum UnsafeSource {
13721367
UserProvided,
13731368
}
13741369

1370+
/// Track whether under `feature(min_generic_const_args)` this anon const
1371+
/// was explicitly disambiguated as an anon const or not through the use of
1372+
/// `const { ... }` syntax.
1373+
#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy, Walkable)]
1374+
pub enum MgcaDisambiguation {
1375+
AnonConst,
1376+
Direct,
1377+
}
1378+
13751379
/// A constant (expression) that's not an item or associated item,
13761380
/// but needs its own `DefId` for type-checking, const-eval, etc.
13771381
/// These are usually found nested inside types (e.g., array lengths)
@@ -1381,6 +1385,7 @@ pub enum UnsafeSource {
13811385
pub struct AnonConst {
13821386
pub id: NodeId,
13831387
pub value: Box<Expr>,
1388+
pub mgca_disambiguation: MgcaDisambiguation,
13841389
}
13851390

13861391
/// An expression.
@@ -1399,26 +1404,20 @@ impl Expr {
13991404
///
14001405
/// This will unwrap at most one block level (curly braces). After that, if the expression
14011406
/// is a path, it mostly dispatches to [`Path::is_potential_trivial_const_arg`].
1402-
/// See there for more info about `allow_mgca_arg`.
14031407
///
1404-
/// The only additional thing to note is that when `allow_mgca_arg` is false, this function
1405-
/// will only allow paths with no qself, before dispatching to the `Path` function of
1406-
/// the same name.
1408+
/// This function will only allow paths with no qself, before dispatching to the `Path`
1409+
/// function of the same name.
14071410
///
14081411
/// Does not ensure that the path resolves to a const param/item, the caller should check this.
14091412
/// This also does not consider macros, so it's only correct after macro-expansion.
1410-
pub fn is_potential_trivial_const_arg(&self, allow_mgca_arg: bool) -> bool {
1413+
pub fn is_potential_trivial_const_arg(&self) -> bool {
14111414
let this = self.maybe_unwrap_block();
1412-
if allow_mgca_arg {
1413-
matches!(this.kind, ExprKind::Path(..))
1415+
if let ExprKind::Path(None, path) = &this.kind
1416+
&& path.is_potential_trivial_const_arg()
1417+
{
1418+
true
14141419
} else {
1415-
if let ExprKind::Path(None, path) = &this.kind
1416-
&& path.is_potential_trivial_const_arg(allow_mgca_arg)
1417-
{
1418-
true
1419-
} else {
1420-
false
1421-
}
1420+
false
14221421
}
14231422
}
14241423

compiler/rustc_ast/src/visit.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,7 @@ macro_rules! common_visitor_and_walkers {
415415
UnsafeBinderCastKind,
416416
BinOpKind,
417417
BlockCheckMode,
418+
MgcaDisambiguation,
418419
BorrowKind,
419420
BoundAsyncness,
420421
BoundConstness,

compiler/rustc_ast_lowering/src/expr.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -484,7 +484,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
484484
arg
485485
};
486486

487-
let anon_const = AnonConst { id: node_id, value: const_value };
487+
let anon_const = AnonConst {
488+
id: node_id,
489+
value: const_value,
490+
mgca_disambiguation: MgcaDisambiguation::AnonConst,
491+
};
488492
generic_args.push(AngleBracketedArg::Arg(GenericArg::Const(anon_const)));
489493
} else {
490494
real_args.push(arg);

compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 64 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1206,7 +1206,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
12061206
.and_then(|partial_res| partial_res.full_res())
12071207
{
12081208
if !res.matches_ns(Namespace::TypeNS)
1209-
&& path.is_potential_trivial_const_arg(false)
1209+
&& path.is_potential_trivial_const_arg()
12101210
{
12111211
debug!(
12121212
"lower_generic_arg: Lowering type argument as const argument: {:?}",
@@ -2276,11 +2276,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
22762276
) -> &'hir hir::ConstArg<'hir> {
22772277
let tcx = self.tcx;
22782278

2279-
let ct_kind = if path
2280-
.is_potential_trivial_const_arg(tcx.features().min_generic_const_args())
2281-
&& (tcx.features().min_generic_const_args()
2282-
|| matches!(res, Res::Def(DefKind::ConstParam, _)))
2283-
{
2279+
let is_trivial_path = path.is_potential_trivial_const_arg()
2280+
&& matches!(res, Res::Def(DefKind::ConstParam, _));
2281+
let ct_kind = if is_trivial_path || tcx.features().min_generic_const_args() {
22842282
let qpath = self.lower_qpath(
22852283
ty_id,
22862284
&None,
@@ -2359,6 +2357,50 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
23592357
}
23602358
}
23612359

2360+
#[instrument(level = "debug", skip(self), ret)]
2361+
fn lower_expr_to_const_arg_direct(&mut self, expr: &Expr) -> hir::ConstArg<'hir> {
2362+
let overly_complex_const = |this: &mut Self| {
2363+
let e = this.dcx().struct_span_err(
2364+
expr.span,
2365+
"complex const arguments must be placed inside of a `const` block",
2366+
);
2367+
2368+
ConstArg { hir_id: this.next_id(), kind: hir::ConstArgKind::Error(expr.span, e.emit()) }
2369+
};
2370+
2371+
match &expr.kind {
2372+
ExprKind::Path(qself, path) => {
2373+
let qpath = self.lower_qpath(
2374+
expr.id,
2375+
qself,
2376+
path,
2377+
ParamMode::Explicit,
2378+
AllowReturnTypeNotation::No,
2379+
// FIXME(mgca): update for `fn foo() -> Bar<FOO<impl Trait>>` support
2380+
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
2381+
None,
2382+
);
2383+
2384+
ConstArg { hir_id: self.next_id(), kind: hir::ConstArgKind::Path(qpath) }
2385+
}
2386+
ExprKind::Underscore => ConstArg {
2387+
hir_id: self.lower_node_id(expr.id),
2388+
kind: hir::ConstArgKind::Infer(expr.span, ()),
2389+
},
2390+
ExprKind::Block(block, _) => {
2391+
if let [stmt] = block.stmts.as_slice()
2392+
&& let StmtKind::Expr(expr) = &stmt.kind
2393+
&& matches!(expr.kind, ExprKind::Path(..) | ExprKind::Struct(..))
2394+
{
2395+
return self.lower_expr_to_const_arg_direct(expr);
2396+
}
2397+
2398+
overly_complex_const(self)
2399+
}
2400+
_ => overly_complex_const(self),
2401+
}
2402+
}
2403+
23622404
/// See [`hir::ConstArg`] for when to use this function vs
23632405
/// [`Self::lower_anon_const_to_anon_const`].
23642406
fn lower_anon_const_to_const_arg(&mut self, anon: &AnonConst) -> &'hir hir::ConstArg<'hir> {
@@ -2379,20 +2421,32 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
23792421
} else {
23802422
&anon.value
23812423
};
2424+
2425+
if tcx.features().min_generic_const_args() {
2426+
match anon.mgca_disambiguation {
2427+
MgcaDisambiguation::AnonConst => {
2428+
let lowered_anon = self.lower_anon_const_to_anon_const(anon);
2429+
return ConstArg {
2430+
hir_id: self.next_id(),
2431+
kind: hir::ConstArgKind::Anon(lowered_anon),
2432+
};
2433+
}
2434+
MgcaDisambiguation::Direct => return self.lower_expr_to_const_arg_direct(expr),
2435+
}
2436+
}
2437+
23822438
let maybe_res =
23832439
self.resolver.get_partial_res(expr.id).and_then(|partial_res| partial_res.full_res());
23842440
if let ExprKind::Path(qself, path) = &expr.kind
2385-
&& path.is_potential_trivial_const_arg(tcx.features().min_generic_const_args())
2386-
&& (tcx.features().min_generic_const_args()
2387-
|| matches!(maybe_res, Some(Res::Def(DefKind::ConstParam, _))))
2441+
&& path.is_potential_trivial_const_arg()
2442+
&& matches!(maybe_res, Some(Res::Def(DefKind::ConstParam, _)))
23882443
{
23892444
let qpath = self.lower_qpath(
23902445
expr.id,
23912446
qself,
23922447
path,
23932448
ParamMode::Explicit,
23942449
AllowReturnTypeNotation::No,
2395-
// FIXME(mgca): update for `fn foo() -> Bar<FOO<impl Trait>>` support
23962450
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
23972451
None,
23982452
);

compiler/rustc_ast_passes/src/feature_gate.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
514514
gate_all!(fn_delegation, "functions delegation is not yet fully implemented");
515515
gate_all!(postfix_match, "postfix match is experimental");
516516
gate_all!(mut_ref, "mutable by-reference bindings are experimental");
517+
gate_all!(min_generic_const_args, "unbraced const blocks as const args are experimental");
517518
gate_all!(global_registration, "global registration is experimental");
518519
gate_all!(return_type_notation, "return type notation is experimental");
519520
gate_all!(pin_ergonomics, "pinned reference syntax is experimental");

compiler/rustc_builtin_macros/src/autodiff.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ mod llvm_enzyme {
1717
use rustc_ast::{
1818
self as ast, AngleBracketedArg, AngleBracketedArgs, AnonConst, AssocItemKind, BindingMode,
1919
FnRetTy, FnSig, GenericArg, GenericArgs, GenericParamKind, Generics, ItemKind,
20-
MetaItemInner, PatKind, Path, PathSegment, TyKind, Visibility,
20+
MetaItemInner, MgcaDisambiguation, PatKind, Path, PathSegment, TyKind, Visibility,
2121
};
2222
use rustc_expand::base::{Annotatable, ExtCtxt};
2323
use rustc_span::{Ident, Span, Symbol, sym};
@@ -558,7 +558,11 @@ mod llvm_enzyme {
558558
}
559559
GenericParamKind::Const { .. } => {
560560
let expr = ecx.expr_path(ast::Path::from_ident(p.ident));
561-
let anon_const = AnonConst { id: ast::DUMMY_NODE_ID, value: expr };
561+
let anon_const = AnonConst {
562+
id: ast::DUMMY_NODE_ID,
563+
value: expr,
564+
mgca_disambiguation: MgcaDisambiguation::Direct,
565+
};
562566
Some(AngleBracketedArg::Arg(GenericArg::Const(anon_const)))
563567
}
564568
GenericParamKind::Lifetime { .. } => None,
@@ -813,6 +817,7 @@ mod llvm_enzyme {
813817
let anon_const = rustc_ast::AnonConst {
814818
id: ast::DUMMY_NODE_ID,
815819
value: ecx.expr_usize(span, 1 + x.width as usize),
820+
mgca_disambiguation: MgcaDisambiguation::Direct,
816821
};
817822
TyKind::Array(ty.clone(), anon_const)
818823
};
@@ -827,6 +832,7 @@ mod llvm_enzyme {
827832
let anon_const = rustc_ast::AnonConst {
828833
id: ast::DUMMY_NODE_ID,
829834
value: ecx.expr_usize(span, x.width as usize),
835+
mgca_disambiguation: MgcaDisambiguation::Direct,
830836
};
831837
let kind = TyKind::Array(ty.clone(), anon_const);
832838
let ty =

compiler/rustc_builtin_macros/src/pattern_type.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use rustc_ast::tokenstream::TokenStream;
2-
use rustc_ast::{AnonConst, DUMMY_NODE_ID, Ty, TyPat, TyPatKind, ast, token};
2+
use rustc_ast::{AnonConst, DUMMY_NODE_ID, MgcaDisambiguation, Ty, TyPat, TyPatKind, ast, token};
33
use rustc_errors::PResult;
44
use rustc_expand::base::{self, DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult};
55
use rustc_parse::exp;
@@ -60,8 +60,20 @@ fn ty_pat(kind: TyPatKind, span: Span) -> TyPat {
6060
fn pat_to_ty_pat(cx: &mut ExtCtxt<'_>, pat: ast::Pat) -> TyPat {
6161
let kind = match pat.kind {
6262
ast::PatKind::Range(start, end, include_end) => TyPatKind::Range(
63-
start.map(|value| Box::new(AnonConst { id: DUMMY_NODE_ID, value })),
64-
end.map(|value| Box::new(AnonConst { id: DUMMY_NODE_ID, value })),
63+
start.map(|value| {
64+
Box::new(AnonConst {
65+
id: DUMMY_NODE_ID,
66+
value,
67+
mgca_disambiguation: MgcaDisambiguation::Direct,
68+
})
69+
}),
70+
end.map(|value| {
71+
Box::new(AnonConst {
72+
id: DUMMY_NODE_ID,
73+
value,
74+
mgca_disambiguation: MgcaDisambiguation::Direct,
75+
})
76+
}),
6577
include_end,
6678
),
6779
ast::PatKind::Or(variants) => {

compiler/rustc_expand/src/build.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ use rustc_ast::token::Delimiter;
22
use rustc_ast::tokenstream::TokenStream;
33
use rustc_ast::util::literal;
44
use rustc_ast::{
5-
self as ast, AnonConst, AttrItem, AttrVec, BlockCheckMode, Expr, LocalKind, MatchKind, PatKind,
6-
UnOp, attr, token, tokenstream,
5+
self as ast, AnonConst, AttrItem, AttrVec, BlockCheckMode, Expr, LocalKind, MatchKind,
6+
MgcaDisambiguation, PatKind, UnOp, attr, token, tokenstream,
77
};
88
use rustc_span::source_map::Spanned;
99
use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym};
@@ -101,6 +101,7 @@ impl<'a> ExtCtxt<'a> {
101101
attrs: AttrVec::new(),
102102
tokens: None,
103103
}),
104+
mgca_disambiguation: MgcaDisambiguation::Direct,
104105
}
105106
}
106107

compiler/rustc_parse/src/parser/asm.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use rustc_ast::{self as ast, AsmMacro};
1+
use rustc_ast::{self as ast, AsmMacro, MgcaDisambiguation};
22
use rustc_span::{Span, Symbol, kw};
33

44
use super::{ExpKeywordPair, ForceCollect, IdentIsRaw, Trailing, UsePreAttrPos};
@@ -149,7 +149,7 @@ fn parse_asm_operand<'a>(
149149
let block = p.parse_block()?;
150150
ast::InlineAsmOperand::Label { block }
151151
} else if p.eat_keyword(exp!(Const)) {
152-
let anon_const = p.parse_expr_anon_const()?;
152+
let anon_const = p.parse_expr_anon_const(MgcaDisambiguation::AnonConst)?;
153153
ast::InlineAsmOperand::Const { anon_const }
154154
} else if p.eat_keyword(exp!(Sym)) {
155155
let expr = p.parse_expr()?;

compiler/rustc_parse/src/parser/diagnostics.rs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ use rustc_ast::token::{self, Lit, LitKind, Token, TokenKind};
66
use rustc_ast::util::parser::AssocOp;
77
use rustc_ast::{
88
self as ast, AngleBracketedArg, AngleBracketedArgs, AnonConst, AttrVec, BinOpKind, BindingMode,
9-
Block, BlockCheckMode, Expr, ExprKind, GenericArg, Generics, Item, ItemKind, Param, Pat,
10-
PatKind, Path, PathSegment, QSelf, Recovered, Ty, TyKind,
9+
Block, BlockCheckMode, Expr, ExprKind, GenericArg, Generics, Item, ItemKind,
10+
MgcaDisambiguation, Param, Pat, PatKind, Path, PathSegment, QSelf, Recovered, Ty, TyKind,
1111
};
1212
use rustc_ast_pretty::pprust;
1313
use rustc_data_structures::fx::FxHashSet;
@@ -2627,7 +2627,11 @@ impl<'a> Parser<'a> {
26272627
self.dcx().emit_err(UnexpectedConstParamDeclaration { span: param.span(), sugg });
26282628

26292629
let value = self.mk_expr_err(param.span(), guar);
2630-
Some(GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value }))
2630+
Some(GenericArg::Const(AnonConst {
2631+
id: ast::DUMMY_NODE_ID,
2632+
value,
2633+
mgca_disambiguation: MgcaDisambiguation::Direct,
2634+
}))
26312635
}
26322636

26332637
pub(super) fn recover_const_param_declaration(
@@ -2711,7 +2715,11 @@ impl<'a> Parser<'a> {
27112715
);
27122716
let guar = err.emit();
27132717
let value = self.mk_expr_err(start.to(expr.span), guar);
2714-
return Ok(GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value }));
2718+
return Ok(GenericArg::Const(AnonConst {
2719+
id: ast::DUMMY_NODE_ID,
2720+
value,
2721+
mgca_disambiguation: MgcaDisambiguation::Direct,
2722+
}));
27152723
} else if snapshot.token == token::Colon
27162724
&& expr.span.lo() == snapshot.token.span.hi()
27172725
&& matches!(expr.kind, ExprKind::Path(..))
@@ -2780,7 +2788,11 @@ impl<'a> Parser<'a> {
27802788
);
27812789
let guar = err.emit();
27822790
let value = self.mk_expr_err(span, guar);
2783-
GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value })
2791+
GenericArg::Const(AnonConst {
2792+
id: ast::DUMMY_NODE_ID,
2793+
value,
2794+
mgca_disambiguation: MgcaDisambiguation::Direct,
2795+
})
27842796
}
27852797

27862798
/// Some special error handling for the "top-level" patterns in a match arm,

0 commit comments

Comments
 (0)