Skip to content

Commit 8f74277

Browse files
committed
allow implicit anon consts for literals
1 parent e18c200 commit 8f74277

File tree

45 files changed

+221
-188
lines changed

Some content is hidden

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

45 files changed

+221
-188
lines changed

compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2422,15 +2422,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
24222422
return match anon.mgca_disambiguation {
24232423
MgcaDisambiguation::AnonConst => {
24242424
let lowered_anon = self.lower_anon_const_to_anon_const(anon);
2425-
ConstArg {
2426-
hir_id: self.next_id(),
2427-
kind: hir::ConstArgKind::Anon(lowered_anon),
2428-
}
2429-
}
2430-
MgcaDisambiguation::Direct => {
2431-
self.lower_expr_to_const_arg_direct(&anon.value)
2425+
ConstArg { hir_id: self.next_id(), kind: hir::ConstArgKind::Anon(lowered_anon) }
24322426
}
2433-
}
2427+
MgcaDisambiguation::Direct => self.lower_expr_to_const_arg_direct(&anon.value),
2428+
};
24342429
}
24352430

24362431
// Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments

compiler/rustc_parse/src/parser/asm.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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(MgcaDisambiguation::AnonConst)?;
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: 9 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,15 @@ use crate::errors::{
3131
AddParen, AmbiguousPlus, AsyncMoveBlockIn2015, AsyncUseBlockIn2015, AttributeOnParamType,
3232
AwaitSuggestion, BadQPathStage2, BadTypePlus, BadTypePlusSub, ColonAsSemi,
3333
ComparisonOperatorsCannotBeChained, ComparisonOperatorsCannotBeChainedSugg,
34-
ConstGenericWithoutBraces, ConstGenericWithoutBracesSugg, DocCommentDoesNotDocumentAnything,
35-
DocCommentOnParamType, DoubleColonInBound, ExpectedIdentifier, ExpectedSemi, ExpectedSemiSugg,
36-
GenericParamsWithoutAngleBrackets, GenericParamsWithoutAngleBracketsSugg,
37-
HelpIdentifierStartsWithNumber, HelpUseLatestEdition, InInTypo, IncorrectAwait,
38-
IncorrectSemicolon, IncorrectUseOfAwait, IncorrectUseOfUse, PatternMethodParamWithoutBody,
39-
QuestionMarkInType, QuestionMarkInTypeSugg, SelfParamNotFirst, StructLiteralBodyWithoutPath,
40-
StructLiteralBodyWithoutPathSugg, SuggAddMissingLetStmt, SuggEscapeIdentifier, SuggRemoveComma,
41-
TernaryOperator, TernaryOperatorSuggestion, UnexpectedConstInGenericParam,
42-
UnexpectedConstParamDeclaration, UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets,
43-
UseEqInstead, WrapType,
34+
DocCommentDoesNotDocumentAnything, DocCommentOnParamType, DoubleColonInBound,
35+
ExpectedIdentifier, ExpectedSemi, ExpectedSemiSugg, GenericParamsWithoutAngleBrackets,
36+
GenericParamsWithoutAngleBracketsSugg, HelpIdentifierStartsWithNumber, HelpUseLatestEdition,
37+
InInTypo, IncorrectAwait, IncorrectSemicolon, IncorrectUseOfAwait, IncorrectUseOfUse,
38+
PatternMethodParamWithoutBody, QuestionMarkInType, QuestionMarkInTypeSugg, SelfParamNotFirst,
39+
StructLiteralBodyWithoutPath, StructLiteralBodyWithoutPathSugg, SuggAddMissingLetStmt,
40+
SuggEscapeIdentifier, SuggRemoveComma, TernaryOperator, TernaryOperatorSuggestion,
41+
UnexpectedConstInGenericParam, UnexpectedConstParamDeclaration,
42+
UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets, UseEqInstead, WrapType,
4443
};
4544
use crate::parser::FnContext;
4645
use crate::parser::attr::InnerAttrPolicy;
@@ -2558,36 +2557,6 @@ impl<'a> Parser<'a> {
25582557
Ok(false) // Don't continue.
25592558
}
25602559

2561-
/// Attempt to parse a generic const argument that has not been enclosed in braces.
2562-
/// There are a limited number of expressions that are permitted without being encoded
2563-
/// in braces:
2564-
/// - Literals.
2565-
/// - Single-segment paths (i.e. standalone generic const parameters).
2566-
/// All other expressions that can be parsed will emit an error suggesting the expression be
2567-
/// wrapped in braces.
2568-
pub(super) fn handle_unambiguous_unbraced_const_arg(&mut self) -> PResult<'a, Box<Expr>> {
2569-
let start = self.token.span;
2570-
let attrs = self.parse_outer_attributes()?;
2571-
let (expr, _) =
2572-
self.parse_expr_res(Restrictions::CONST_EXPR, attrs).map_err(|mut err| {
2573-
err.span_label(
2574-
start.shrink_to_lo(),
2575-
"while parsing a const generic argument starting here",
2576-
);
2577-
err
2578-
})?;
2579-
if !self.expr_is_valid_const_arg(&expr) {
2580-
self.dcx().emit_err(ConstGenericWithoutBraces {
2581-
span: expr.span,
2582-
sugg: ConstGenericWithoutBracesSugg {
2583-
left: expr.span.shrink_to_lo(),
2584-
right: expr.span.shrink_to_hi(),
2585-
},
2586-
});
2587-
}
2588-
Ok(expr)
2589-
}
2590-
25912560
fn recover_const_param_decl(&mut self, ty_generics: Option<&Generics>) -> Option<GenericArg> {
25922561
let snapshot = self.create_snapshot_for_diagnostic();
25932562
let param = match self.parse_const_param(AttrVec::new()) {

compiler/rustc_parse/src/parser/expr.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,13 @@ impl<'a> Parser<'a> {
8787

8888
pub fn parse_expr_anon_const(
8989
&mut self,
90-
mgca_disambiguation: MgcaDisambiguation,
90+
mgca_disambiguation: impl FnOnce(&Self, &Expr) -> MgcaDisambiguation,
9191
) -> PResult<'a, AnonConst> {
92-
self.parse_expr().map(|value| AnonConst { id: DUMMY_NODE_ID, value, mgca_disambiguation })
92+
self.parse_expr().map(|value| AnonConst {
93+
id: DUMMY_NODE_ID,
94+
mgca_disambiguation: mgca_disambiguation(self, &value),
95+
value,
96+
})
9397
}
9498

9599
fn parse_expr_catch_underscore(
@@ -1626,9 +1630,9 @@ impl<'a> Parser<'a> {
16261630
// complicate the DefCollector and likely all other visitors.
16271631
// So we strip the const blockiness and just store it as a block
16281632
// in the AST with the extra disambiguator on the AnonConst
1629-
self.parse_expr_anon_const(MgcaDisambiguation::AnonConst)?
1633+
self.parse_expr_anon_const(|_, _| MgcaDisambiguation::AnonConst)?
16301634
} else {
1631-
self.parse_expr_anon_const(MgcaDisambiguation::Direct)?
1635+
self.parse_expr_anon_const(|this, expr| this.mgca_direct_lit_hack(expr))?
16321636
};
16331637
self.expect(close)?;
16341638
ExprKind::Repeat(first_expr, count)

compiler/rustc_parse/src/parser/item.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1651,7 +1651,7 @@ impl<'a> Parser<'a> {
16511651
};
16521652

16531653
let disr_expr = if this.eat(exp!(Eq)) {
1654-
Some(this.parse_expr_anon_const(MgcaDisambiguation::AnonConst)?)
1654+
Some(this.parse_expr_anon_const(|_, _| MgcaDisambiguation::AnonConst)?)
16551655
} else {
16561656
None
16571657
};
@@ -1867,7 +1867,7 @@ impl<'a> Parser<'a> {
18671867
if p.token == token::Eq {
18681868
let mut snapshot = p.create_snapshot_for_diagnostic();
18691869
snapshot.bump();
1870-
match snapshot.parse_expr_anon_const(MgcaDisambiguation::AnonConst) {
1870+
match snapshot.parse_expr_anon_const(|_, _| MgcaDisambiguation::AnonConst) {
18711871
Ok(const_expr) => {
18721872
let sp = ty.span.shrink_to_hi().to(const_expr.value.span);
18731873
p.psess.gated_spans.gate(sym::default_field_values, sp);
@@ -2069,7 +2069,7 @@ impl<'a> Parser<'a> {
20692069
}
20702070
let default = if self.token == token::Eq {
20712071
self.bump();
2072-
let const_expr = self.parse_expr_anon_const(MgcaDisambiguation::AnonConst)?;
2072+
let const_expr = self.parse_expr_anon_const(|_, _| MgcaDisambiguation::AnonConst)?;
20732073
let sp = ty.span.shrink_to_hi().to(const_expr.value.span);
20742074
self.psess.gated_spans.gate(sym::default_field_values, sp);
20752075
Some(const_expr)

compiler/rustc_parse/src/parser/path.rs

Lines changed: 59 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,13 @@ use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
1616
use super::{Parser, Restrictions, TokenType};
1717
use crate::ast::{PatKind, TyKind};
1818
use crate::errors::{
19-
self, AttributeOnEmptyType, AttributeOnGenericArg, FnPathFoundNamedParams,
20-
PathFoundAttributeInParams, PathFoundCVariadicParams, PathSingleColon, PathTripleColon,
19+
self, AttributeOnEmptyType, AttributeOnGenericArg, ConstGenericWithoutBraces,
20+
ConstGenericWithoutBracesSugg, FnPathFoundNamedParams, PathFoundAttributeInParams,
21+
PathFoundCVariadicParams, PathSingleColon, PathTripleColon,
2122
};
2223
use crate::exp;
2324
use crate::parser::{
24-
CommaRecoveryMode, ExprKind, FnContext, FnParseMode, RecoverColon, RecoverComma,
25+
CommaRecoveryMode, Expr, ExprKind, FnContext, FnParseMode, RecoverColon, RecoverComma,
2526
};
2627

2728
/// Specifies how to parse a path.
@@ -882,12 +883,65 @@ impl<'a> Parser<'a> {
882883
let value = self.parse_mgca_const_block(true)?;
883884
(value.value, MgcaDisambiguation::AnonConst)
884885
} else {
885-
let value = self.handle_unambiguous_unbraced_const_arg()?;
886-
(value, MgcaDisambiguation::Direct)
886+
self.parse_unambiguous_unbraced_const_arg()?
887887
};
888888
Ok(AnonConst { id: ast::DUMMY_NODE_ID, value, mgca_disambiguation })
889889
}
890890

891+
/// Attempt to parse a const argument that has not been enclosed in braces.
892+
/// There are a limited number of expressions that are permitted without being
893+
/// enclosed in braces:
894+
/// - Literals.
895+
/// - Single-segment paths (i.e. standalone generic const parameters).
896+
/// All other expressions that can be parsed will emit an error suggesting the expression be
897+
/// wrapped in braces.
898+
pub(super) fn parse_unambiguous_unbraced_const_arg(
899+
&mut self,
900+
) -> PResult<'a, (Box<Expr>, MgcaDisambiguation)> {
901+
let start = self.token.span;
902+
let attrs = self.parse_outer_attributes()?;
903+
let (expr, _) =
904+
self.parse_expr_res(Restrictions::CONST_EXPR, attrs).map_err(|mut err| {
905+
err.span_label(
906+
start.shrink_to_lo(),
907+
"while parsing a const generic argument starting here",
908+
);
909+
err
910+
})?;
911+
if !self.expr_is_valid_const_arg(&expr) {
912+
self.dcx().emit_err(ConstGenericWithoutBraces {
913+
span: expr.span,
914+
sugg: ConstGenericWithoutBracesSugg {
915+
left: expr.span.shrink_to_lo(),
916+
right: expr.span.shrink_to_hi(),
917+
},
918+
});
919+
}
920+
921+
let mgca_disambiguation = self.mgca_direct_lit_hack(&expr);
922+
Ok((expr, mgca_disambiguation))
923+
}
924+
925+
/// Under `min_generic_const_args` we still allow *some* anon consts to be written without
926+
/// a `const` block as it makes things quite a lot nicer. This function is useful for contexts
927+
/// where we would like to use `MgcaDisambiguation::Direct` but need to fudge it to be `AnonConst`
928+
/// in the presence of literals.
929+
//
930+
/// FIXME(min_generic_const_args): In the long term it would be nice to have a way to directly
931+
/// represent literals in `hir::ConstArgKind` so that we can remove this special case by not
932+
/// needing an anon const.
933+
pub fn mgca_direct_lit_hack(&self, expr: &Expr) -> MgcaDisambiguation {
934+
match &expr.kind {
935+
ast::ExprKind::Lit(_) => MgcaDisambiguation::AnonConst,
936+
ast::ExprKind::Unary(ast::UnOp::Neg, expr)
937+
if matches!(expr.kind, ast::ExprKind::Lit(_)) =>
938+
{
939+
MgcaDisambiguation::AnonConst
940+
}
941+
_ => MgcaDisambiguation::Direct,
942+
}
943+
}
944+
891945
/// Parse a generic argument in a path segment.
892946
/// This does not include constraints, e.g., `Item = u8`, which is handled in `parse_angle_arg`.
893947
pub(super) fn parse_generic_arg(

compiler/rustc_parse/src/parser/ty.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -668,7 +668,7 @@ impl<'a> Parser<'a> {
668668
// in the AST with the extra disambiguator on the AnonConst
669669
self.parse_mgca_const_block(false)?
670670
} else {
671-
self.parse_expr_anon_const(MgcaDisambiguation::Direct)?
671+
self.parse_expr_anon_const(|this, expr| this.mgca_direct_lit_hack(expr))?
672672
};
673673

674674
if let Err(e) = self.expect(exp!(CloseBracket)) {
@@ -713,7 +713,7 @@ impl<'a> Parser<'a> {
713713

714714
// FIXME(mgca): recovery is broken for `const {` args
715715
// we first try to parse pattern like `[u8 5]`
716-
let length = match self.parse_expr_anon_const(MgcaDisambiguation::Direct) {
716+
let length = match self.parse_expr_anon_const(|_, _| MgcaDisambiguation::Direct) {
717717
Ok(length) => length,
718718
Err(e) => {
719719
e.cancel();
@@ -801,7 +801,7 @@ impl<'a> Parser<'a> {
801801
/// an error type.
802802
fn parse_typeof_ty(&mut self, lo: Span) -> PResult<'a, TyKind> {
803803
self.expect(exp!(OpenParen))?;
804-
let _expr = self.parse_expr_anon_const(MgcaDisambiguation::AnonConst)?;
804+
let _expr = self.parse_expr_anon_const(|_, _| MgcaDisambiguation::AnonConst)?;
805805
self.expect(exp!(CloseParen))?;
806806
let span = lo.to(self.prev_token.span);
807807
let guar = self

src/tools/clippy/tests/ui/trait_duplication_in_bounds_assoc_const_eq.fixed

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ trait AssocConstTrait {
88
}
99
fn assoc_const_args<T>()
1010
where
11-
T: AssocConstTrait<ASSOC = const { 0 }>,
11+
T: AssocConstTrait<ASSOC = 0>,
1212
//~^ trait_duplication_in_bounds
1313
{
1414
}

src/tools/clippy/tests/ui/trait_duplication_in_bounds_assoc_const_eq.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ trait AssocConstTrait {
88
}
99
fn assoc_const_args<T>()
1010
where
11-
T: AssocConstTrait<ASSOC = const { 0 }> + AssocConstTrait<ASSOC = const { 0 }>,
11+
T: AssocConstTrait<ASSOC = 0> + AssocConstTrait<ASSOC = 0>,
1212
//~^ trait_duplication_in_bounds
1313
{
1414
}

src/tools/clippy/tests/ui/trait_duplication_in_bounds_assoc_const_eq.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error: these where clauses contain repeated elements
22
--> tests/ui/trait_duplication_in_bounds_assoc_const_eq.rs:11:8
33
|
4-
LL | T: AssocConstTrait<ASSOC = const { 0 }> + AssocConstTrait<ASSOC = const { 0 }>,
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `AssocConstTrait<ASSOC = const { 0 }>`
4+
LL | T: AssocConstTrait<ASSOC = 0> + AssocConstTrait<ASSOC = 0>,
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `AssocConstTrait<ASSOC = 0>`
66
|
77
note: the lint level is defined here
88
--> tests/ui/trait_duplication_in_bounds_assoc_const_eq.rs:1:9

0 commit comments

Comments
 (0)