Rollup merge of #79164 - varkor:unbraced-single-segment-const-arguments, r=petrochenkov
Permit standalone generic parameters as const generic arguments in macros Fixes https://github.com/rust-lang/rust/issues/79127. r? ```@petrochenkov```
This commit is contained in:
commit
b5fffdc12b
@ -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| {
|
||||
|
@ -489,6 +489,7 @@ 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,
|
||||
@ -496,6 +497,13 @@ impl<'a> Parser<'a> {
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
| ^^^^^^
|
||||
@ -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]
|
||||
| ^^^^^^^^
|
||||
@ -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 }]
|
||||
| ^^^^^^^^^^^^
|
||||
@ -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>
|
||||
| ^^^^^^^
|
||||
@ -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 }>
|
||||
| ^^^^^^^^^^^
|
||||
|
@ -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);
|
||||
| ^^^^^^
|
||||
@ -21,7 +21,7 @@ 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`
|
||||
@ -29,7 +29,7 @@ LL | let _: foo!({{ 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`
|
||||
@ -37,7 +37,7 @@ LL | let _: bar!({ 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`
|
||||
@ -45,7 +45,7 @@ LL | let _: baz!({{ 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`
|
||||
|
@ -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 {
|
||||
@ -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 }});
|
||||
|
Loading…
Reference in New Issue
Block a user