Permit standalone generic parameters as const generic arguments in macros
This commit is contained in:
parent
c4f836ad1a
commit
efcbf1b00b
5 changed files with 18 additions and 28 deletions
|
@ -1808,9 +1808,13 @@ impl<'a> Parser<'a> {
|
||||||
return Ok(false); // Don't continue.
|
return Ok(false); // Don't continue.
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handle a generic const argument that had not been enclosed in braces, and suggest enclosing
|
/// Attempt to parse a generic const argument that has not been enclosed in braces.
|
||||||
/// it braces. In this situation, unlike in `handle_ambiguous_unbraced_const_arg`, this is
|
/// There are a limited number of expressions that are permitted without being encoded
|
||||||
/// almost certainly a const argument, so we always offer a suggestion.
|
/// 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>> {
|
pub fn handle_unambiguous_unbraced_const_arg(&mut self) -> PResult<'a, P<Expr>> {
|
||||||
let start = self.token.span;
|
let start = self.token.span;
|
||||||
let expr = self.parse_expr_res(Restrictions::CONST_EXPR, None).map_err(|mut err| {
|
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 `{}`.
|
/// - An expression surrounded in `{}`.
|
||||||
/// - A literal.
|
/// - A literal.
|
||||||
/// - A numeric literal prefixed by `-`.
|
/// - A numeric literal prefixed by `-`.
|
||||||
|
/// - A single-segment path.
|
||||||
pub(super) fn expr_is_valid_const_arg(&self, expr: &P<rustc_ast::Expr>) -> bool {
|
pub(super) fn expr_is_valid_const_arg(&self, expr: &P<rustc_ast::Expr>) -> bool {
|
||||||
match &expr.kind {
|
match &expr.kind {
|
||||||
ast::ExprKind::Block(_, _) | ast::ExprKind::Lit(_) => true,
|
ast::ExprKind::Block(_, _) | ast::ExprKind::Lit(_) => true,
|
||||||
|
@ -496,6 +497,13 @@ impl<'a> Parser<'a> {
|
||||||
ast::ExprKind::Lit(_) => true,
|
ast::ExprKind::Lit(_) => true,
|
||||||
_ => false,
|
_ => 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,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,3 @@
|
||||||
error: expressions must be enclosed in braces to be used as const generic arguments
|
|
||||||
--> $DIR/macro_rules-braces.rs:34:17
|
|
||||||
|
|
|
||||||
LL | let _: baz!(N);
|
|
||||||
| ^
|
|
||||||
|
|
|
||||||
help: enclose the `const` expression in braces
|
|
||||||
|
|
|
||||||
LL | let _: baz!({ N });
|
|
||||||
| ^ ^
|
|
||||||
|
|
||||||
error: expressions must be enclosed in braces to be used as const generic arguments
|
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:54:17
|
||||||
|
|
|
|
||||||
|
@ -68,5 +57,5 @@ LL | let _: biz!({ N });
|
||||||
= note: this may fail depending on what value the parameter takes
|
= note: this may fail depending on what value the parameter takes
|
||||||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: aborting due to 6 previous errors
|
error: aborting due to 5 previous errors
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,3 @@
|
||||||
error: expressions must be enclosed in braces to be used as const generic arguments
|
|
||||||
--> $DIR/macro_rules-braces.rs:34:17
|
|
||||||
|
|
|
||||||
LL | let _: baz!(N);
|
|
||||||
| ^
|
|
||||||
|
|
|
||||||
help: enclose the `const` expression in braces
|
|
||||||
|
|
|
||||||
LL | let _: baz!({ N });
|
|
||||||
| ^ ^
|
|
||||||
|
|
||||||
error: expressions must be enclosed in braces to be used as const generic arguments
|
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:54:17
|
||||||
|
|
|
|
||||||
|
@ -52,5 +41,5 @@ LL | let _: biz!({ N });
|
||||||
|
|
|
|
||||||
= help: const parameters may only be used as standalone arguments, i.e. `N`
|
= help: const parameters may only be used as standalone arguments, i.e. `N`
|
||||||
|
|
||||||
error: aborting due to 6 previous errors
|
error: aborting due to 5 previous errors
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ fn test<const N: usize>() {
|
||||||
let _: foo!({{ N }}); //[min]~ ERROR generic parameters may not
|
let _: foo!({{ N }}); //[min]~ ERROR generic parameters may not
|
||||||
let _: bar!(N);
|
let _: bar!(N);
|
||||||
let _: bar!({ N }); //[min]~ ERROR generic parameters may not
|
let _: bar!({ N }); //[min]~ ERROR generic parameters may not
|
||||||
let _: baz!(N); //~ ERROR expressions must be enclosed in braces
|
let _: baz!(N);
|
||||||
let _: baz!({ N });
|
let _: baz!({ N });
|
||||||
let _: baz!({{ N }}); //[min]~ ERROR generic parameters may not
|
let _: baz!({{ N }}); //[min]~ ERROR generic parameters may not
|
||||||
let _: biz!(N);
|
let _: biz!(N);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue