Skip to content

Commit

Permalink
Rollup merge of #79164 - varkor:unbraced-single-segment-const-argumen…
Browse files Browse the repository at this point in the history
…ts, r=petrochenkov

Permit standalone generic parameters as const generic arguments in macros

Fixes #79127.

r? ``@petrochenkov``
  • Loading branch information
Dylan-DPC authored Nov 19, 2020
2 parents 406281b + 85bc953 commit 37e64af
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 24 deletions.
10 changes: 7 additions & 3 deletions compiler/rustc_parse/src/parser/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1808,9 +1808,13 @@ impl<'a> Parser<'a> {
return Ok(false); // Don't continue.
}

/// Handle a generic const argument that had not been enclosed in braces, and suggest enclosing
/// it braces. In this situation, unlike in `handle_ambiguous_unbraced_const_arg`, this is
/// almost certainly a const argument, so we always offer a suggestion.
/// Attempt to parse a generic const argument that has not been enclosed in braces.
/// There are a limited number of expressions that are permitted without being encoded
/// in braces:
/// - Literals.
/// - Single-segment paths (i.e. standalone generic const parameters).
/// All other expressions that can be parsed will emit an error suggesting the expression be
/// wrapped in braces.
pub fn handle_unambiguous_unbraced_const_arg(&mut self) -> PResult<'a, P<Expr>> {
let start = self.token.span;
let expr = self.parse_expr_res(Restrictions::CONST_EXPR, None).map_err(|mut err| {
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_parse/src/parser/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -489,13 +489,21 @@ impl<'a> Parser<'a> {
/// - An expression surrounded in `{}`.
/// - A literal.
/// - A numeric literal prefixed by `-`.
/// - A single-segment path.
pub(super) fn expr_is_valid_const_arg(&self, expr: &P<rustc_ast::Expr>) -> bool {
match &expr.kind {
ast::ExprKind::Block(_, _) | ast::ExprKind::Lit(_) => true,
ast::ExprKind::Unary(ast::UnOp::Neg, expr) => match &expr.kind {
ast::ExprKind::Lit(_) => true,
_ => false,
},
// We can only resolve single-segment paths at the moment, because multi-segment paths
// require type-checking: see `visit_generic_arg` in `src/librustc_resolve/late.rs`.
ast::ExprKind::Path(None, path)
if path.segments.len() == 1 && path.segments[0].args.is_none() =>
{
true
}
_ => false,
}
}
Expand Down
20 changes: 10 additions & 10 deletions src/test/ui/const-generics/macro_rules-braces.full.stderr
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
error: expressions must be enclosed in braces to be used as const generic arguments
--> $DIR/macro_rules-braces.rs:34:17
--> $DIR/macro_rules-braces.rs:49:17
|
LL | let _: baz!(N);
| ^
LL | let _: baz!(m::P);
| ^^^^
|
help: enclose the `const` expression in braces
|
LL | let _: baz!({ N });
| ^ ^
LL | let _: baz!({ m::P });
| ^ ^

error: expressions must be enclosed in braces to be used as const generic arguments
--> $DIR/macro_rules-braces.rs:54:17
--> $DIR/macro_rules-braces.rs:69:17
|
LL | let _: baz!(10 + 7);
| ^^^^^^
Expand All @@ -21,7 +21,7 @@ LL | let _: baz!({ 10 + 7 });
| ^ ^

error: constant expression depends on a generic parameter
--> $DIR/macro_rules-braces.rs:10:13
--> $DIR/macro_rules-braces.rs:16:13
|
LL | [u8; $x]
| ^^^^^^^^
Expand All @@ -33,7 +33,7 @@ LL | let _: foo!({{ N }});
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error: constant expression depends on a generic parameter
--> $DIR/macro_rules-braces.rs:15:13
--> $DIR/macro_rules-braces.rs:21:13
|
LL | [u8; { $x }]
| ^^^^^^^^^^^^
Expand All @@ -45,7 +45,7 @@ LL | let _: bar!({ N });
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error: constant expression depends on a generic parameter
--> $DIR/macro_rules-braces.rs:20:13
--> $DIR/macro_rules-braces.rs:26:13
|
LL | Foo<$x>
| ^^^^^^^
Expand All @@ -57,7 +57,7 @@ LL | let _: baz!({{ N }});
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error: constant expression depends on a generic parameter
--> $DIR/macro_rules-braces.rs:25:13
--> $DIR/macro_rules-braces.rs:31:13
|
LL | Foo<{ $x }>
| ^^^^^^^^^^^
Expand Down
20 changes: 10 additions & 10 deletions src/test/ui/const-generics/macro_rules-braces.min.stderr
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
error: expressions must be enclosed in braces to be used as const generic arguments
--> $DIR/macro_rules-braces.rs:34:17
--> $DIR/macro_rules-braces.rs:49:17
|
LL | let _: baz!(N);
| ^
LL | let _: baz!(m::P);
| ^^^^
|
help: enclose the `const` expression in braces
|
LL | let _: baz!({ N });
| ^ ^
LL | let _: baz!({ m::P });
| ^ ^

error: expressions must be enclosed in braces to be used as const generic arguments
--> $DIR/macro_rules-braces.rs:54:17
--> $DIR/macro_rules-braces.rs:69:17
|
LL | let _: baz!(10 + 7);
| ^^^^^^
Expand All @@ -21,31 +21,31 @@ LL | let _: baz!({ 10 + 7 });
| ^ ^

error: generic parameters may not be used in const operations
--> $DIR/macro_rules-braces.rs:31:20
--> $DIR/macro_rules-braces.rs:37:20
|
LL | let _: foo!({{ N }});
| ^ cannot perform const operation using `N`
|
= help: const parameters may only be used as standalone arguments, i.e. `N`

error: generic parameters may not be used in const operations
--> $DIR/macro_rules-braces.rs:33:19
--> $DIR/macro_rules-braces.rs:41:19
|
LL | let _: bar!({ N });
| ^ cannot perform const operation using `N`
|
= help: const parameters may only be used as standalone arguments, i.e. `N`

error: generic parameters may not be used in const operations
--> $DIR/macro_rules-braces.rs:36:20
--> $DIR/macro_rules-braces.rs:46:20
|
LL | let _: baz!({{ N }});
| ^ cannot perform const operation using `N`
|
= help: const parameters may only be used as standalone arguments, i.e. `N`

error: generic parameters may not be used in const operations
--> $DIR/macro_rules-braces.rs:38:19
--> $DIR/macro_rules-braces.rs:51:19
|
LL | let _: biz!({ N });
| ^ cannot perform const operation using `N`
Expand Down
17 changes: 16 additions & 1 deletion src/test/ui/const-generics/macro_rules-braces.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
#![cfg_attr(full, feature(const_generics))]
#![cfg_attr(min, feature(min_const_generics))]

mod m {
pub const P: usize = 0;
}

const Q: usize = 0;

fn test<const N: usize>() {
struct Foo<const M: usize>;
macro_rules! foo {
Expand All @@ -29,13 +35,22 @@ fn test<const N: usize>() {
let _: foo!(N);
let _: foo!({ N });
let _: foo!({{ N }}); //[min]~ ERROR generic parameters may not
let _: foo!(Q);
let _: foo!(m::P);
let _: bar!(N);
let _: bar!({ N }); //[min]~ ERROR generic parameters may not
let _: baz!(N); //~ ERROR expressions must be enclosed in braces
let _: bar!(Q);
let _: bar!(m::P);
let _: baz!(N);
let _: baz!({ N });
let _: baz!({{ N }}); //[min]~ ERROR generic parameters may not
let _: baz!(Q);
let _: baz!({ m::P });
let _: baz!(m::P); //~ ERROR expressions must be enclosed in braces
let _: biz!(N);
let _: biz!({ N }); //[min]~ ERROR generic parameters may not
let _: biz!(Q);
let _: biz!(m::P);
let _: foo!(3);
let _: foo!({ 3 });
let _: foo!({{ 3 }});
Expand Down

0 comments on commit 37e64af

Please sign in to comment.