Skip to content

Commit

Permalink
Be more picky in parse_literal_maybe_minus.
Browse files Browse the repository at this point in the history
By only accepting `NtExpr` if it's a literal (possibly with a unary
minus).

This means various error cases are caught during parsing, instead of
during HIR lowering, and the `ArbitraryExpressionInPattern` error is no
longer needed.
  • Loading branch information
nnethercote committed Jun 17, 2024
1 parent 494db01 commit 74a18a0
Show file tree
Hide file tree
Showing 20 changed files with 109 additions and 135 deletions.
4 changes: 0 additions & 4 deletions compiler/rustc_ast_lowering/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,6 @@ ast_lowering_abi_specified_multiple_times =
.label = previously specified here
.note = these ABIs are equivalent on the current target
ast_lowering_arbitrary_expression_in_pattern =
arbitrary expressions aren't allowed in patterns
.pattern_from_macro_note = the `expr` fragment specifier forces the metavariable's content to be an expression
ast_lowering_argument = argument
ast_lowering_assoc_ty_binding_in_dyn =
Expand Down
9 changes: 0 additions & 9 deletions compiler/rustc_ast_lowering/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -363,15 +363,6 @@ pub struct NeverPatternWithGuard {
pub span: Span,
}

#[derive(Diagnostic)]
#[diag(ast_lowering_arbitrary_expression_in_pattern)]
pub struct ArbitraryExpressionInPattern {
#[primary_span]
pub span: Span,
#[note(ast_lowering_pattern_from_macro_note)]
pub pattern_from_macro_note: bool,
}

#[derive(Diagnostic)]
#[diag(ast_lowering_inclusive_range_with_no_end)]
pub struct InclusiveRangeWithNoEnd {
Expand Down
13 changes: 2 additions & 11 deletions compiler/rustc_ast_lowering/src/pat.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
use super::errors::{
ArbitraryExpressionInPattern, ExtraDoubleDot, MisplacedDoubleDot, SubTupleBinding,
};
use super::errors::{ExtraDoubleDot, MisplacedDoubleDot, SubTupleBinding};
use super::ResolverAstLoweringExt;
use super::{ImplTraitContext, LoweringContext, ParamMode};
use crate::ImplTraitPosition;
Expand Down Expand Up @@ -338,14 +336,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
| ExprKind::Dummy => {}
ExprKind::Path(..) if allow_paths => {}
ExprKind::Unary(UnOp::Neg, inner) if matches!(inner.kind, ExprKind::Lit(_)) => {}
_ => {
let pattern_from_macro = expr.is_approximately_pattern();
let guar = self.dcx().emit_err(ArbitraryExpressionInPattern {
span: expr.span,
pattern_from_macro_note: pattern_from_macro,
});
return self.arena.alloc(self.expr_err(expr.span, guar));
}
kind => panic!("unexpected expr kind {kind:?}"),
}
self.lower_expr(expr)
}
Expand Down
27 changes: 19 additions & 8 deletions compiler/rustc_parse/src/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2197,15 +2197,26 @@ impl<'a> Parser<'a> {
/// Matches `'-' lit | lit` (cf. `ast_validation::AstValidator::check_expr_within_pat`).
/// Keep this in sync with `Token::can_begin_literal_maybe_minus`.
pub fn parse_literal_maybe_minus(&mut self) -> PResult<'a, P<Expr>> {
if let token::Interpolated(nt) = &self.token.kind {
let whole = if let token::Interpolated(nt) = &self.token.kind {
match &**nt {
token::NtExpr(e) | token::NtLiteral(e) => {
let e = e.clone();
self.bump();
return Ok(e);
}
_ => {}
};
token::NtLiteral(e) => Some(e.clone()),
token::NtExpr(e) => match &e.kind {
ExprKind::Lit(_) => Some(e.clone()),
ExprKind::Unary(UnOp::Neg, inner)
if matches!(&inner.kind, ast::ExprKind::Lit(_)) =>
{
Some(e.clone())
}
_ => None,
},
_ => None,
}
} else {
None
};
if let Some(e) = whole {
self.bump();
return Ok(e);
}

let lo = self.token.span;
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/issues/issue-43250.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ fn main() {
macro_rules! m {
($a:expr) => {
let $a = 0;
//~^ ERROR expected pattern, found expression `y`
//~| ERROR expected pattern, found expression `C`
}
}
m!(y);
//~^ ERROR arbitrary expressions aren't allowed in patterns
m!(C);
//~^ ERROR arbitrary expressions aren't allowed in patterns
}
22 changes: 14 additions & 8 deletions tests/ui/issues/issue-43250.stderr
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
error: arbitrary expressions aren't allowed in patterns
--> $DIR/issue-43250.rs:9:8
error: expected pattern, found expression `y`
--> $DIR/issue-43250.rs:6:17
|
LL | let $a = 0;
| ^^ expected pattern
...
LL | m!(y);
| ^
| ----- in this macro invocation
|
= note: the `expr` fragment specifier forces the metavariable's content to be an expression
= note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)

error: arbitrary expressions aren't allowed in patterns
--> $DIR/issue-43250.rs:11:8
error: expected pattern, found expression `C`
--> $DIR/issue-43250.rs:6:17
|
LL | let $a = 0;
| ^^ expected pattern
...
LL | m!(C);
| ^
| ----- in this macro invocation
|
= note: the `expr` fragment specifier forces the metavariable's content to be an expression
= note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to 2 previous errors

4 changes: 2 additions & 2 deletions tests/ui/lowering/expr-in-pat-issue-99380.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
macro_rules! foo {
($p:expr) => {
if let $p = Some(42) {
if let $p = Some(42) { //~ ERROR expected pattern, found expression `Some(3)`
return;
}
};
}

fn main() {
foo!(Some(3)); //~ ERROR arbitrary expressions aren't allowed in patterns
foo!(Some(3));
}
11 changes: 7 additions & 4 deletions tests/ui/lowering/expr-in-pat-issue-99380.stderr
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
error: arbitrary expressions aren't allowed in patterns
--> $DIR/expr-in-pat-issue-99380.rs:10:10
error: expected pattern, found expression `Some(3)`
--> $DIR/expr-in-pat-issue-99380.rs:3:16
|
LL | if let $p = Some(42) {
| ^^ expected pattern
...
LL | foo!(Some(3));
| ^^^^^^^
| ------------- in this macro invocation
|
= note: the `expr` fragment specifier forces the metavariable's content to be an expression
= note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to 1 previous error

4 changes: 2 additions & 2 deletions tests/ui/macros/trace_faulty_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ fn use_bang_macro_as_attr() {}
fn use_derive_macro_as_attr() {}

macro_rules! test {
(let $p:pat = $e:expr) => {test!(($p,$e))};
(let $p:pat = $e:expr) => {test!(($p,$e))}; //~ ERROR expected pattern, found expression `1+1`
// this should be expr
// vvv
(($p:pat, $e:pat)) => {let $p = $e;}; //~ ERROR expected expression, found pattern `1+1`
(($p:pat, $e:pat)) => {let $p = $e;};
}

fn foo() {
Expand Down
15 changes: 5 additions & 10 deletions tests/ui/macros/trace_faulty_macros.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -69,22 +69,18 @@ LL | #[derive(Debug)]
LL | fn use_derive_macro_as_attr() {}
| -------------------------------- not a `struct`, `enum` or `union`

error: expected expression, found pattern `1+1`
--> $DIR/trace_faulty_macros.rs:49:37
error: expected pattern, found expression `1+1`
--> $DIR/trace_faulty_macros.rs:46:42
|
LL | (let $p:pat = $e:expr) => {test!(($p,$e))};
| -- this is interpreted as expression, but it is expected to be pattern
| ^^ expected pattern
...
LL | (($p:pat, $e:pat)) => {let $p = $e;};
| ^^ expected expression
| ------ while parsing argument for this `pat` macro fragment
...
LL | test!(let x = 1+1);
| ------------------
| | |
| | this is expected to be expression
| in this macro invocation
| ------------------ in this macro invocation
|
= note: when forwarding a matched fragment to another macro-by-example, matchers in the second macro will see an opaque AST of the fragment type, not the underlying tokens
= note: this error originates in the macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)

note: trace_macro
Expand All @@ -107,7 +103,6 @@ LL | test!(let x = 1+1);
= note: expanding `test! { let x = 1+1 }`
= note: to `test! ((x, 1+1))`
= note: expanding `test! { (x, 1+1) }`
= note: to `let x = 1+1;`

error: aborting due to 5 previous errors

Expand Down
2 changes: 1 addition & 1 deletion tests/ui/macros/vec-macro-in-pattern.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

fn main() {
match Some(vec![42]) {
Some(vec![43]) => {} //~ ERROR arbitrary expressions aren't allowed in patterns
Some(vec![43]) => {} //~ ERROR expected pattern, found expression
_ => {}
}
}
9 changes: 6 additions & 3 deletions tests/ui/macros/vec-macro-in-pattern.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
error: arbitrary expressions aren't allowed in patterns
error: expected pattern, found expression `< [_] > :: into_vec(#[rustc_box] $crate :: boxed :: Box :: new([43]))`
--> $DIR/vec-macro-in-pattern.rs:7:14
|
LL | Some(vec![43]) => {}
| ^^^^^^^^
| |
| expected pattern
| in this macro invocation
| this macro call doesn't expand to a pattern
|
= note: the `expr` fragment specifier forces the metavariable's content to be an expression
= note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
= note: this error originates in the macro `$crate::__rust_force_expr` which comes from the expansion of the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to 1 previous error

3 changes: 1 addition & 2 deletions tests/ui/match/expr_before_ident_pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@ macro_rules! funny {
($a:expr, $b:ident) => {
match [1, 2] {
[$a, $b] => {}
//~^ ERROR expected pattern, found expression `a`
}
};
}

fn main() {
funny!(a, a);
//~^ ERROR cannot find value `a` in this scope
//~| ERROR arbitrary expressions aren't allowed in patterns
}
20 changes: 8 additions & 12 deletions tests/ui/match/expr_before_ident_pat.stderr
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
error[E0425]: cannot find value `a` in this scope
--> $DIR/expr_before_ident_pat.rs:10:12
error: expected pattern, found expression `a`
--> $DIR/expr_before_ident_pat.rs:4:14
|
LL | [$a, $b] => {}
| ^^ expected pattern
...
LL | funny!(a, a);
| ^ not found in this scope

error: arbitrary expressions aren't allowed in patterns
--> $DIR/expr_before_ident_pat.rs:10:12
|
LL | funny!(a, a);
| ^
| ------------ in this macro invocation
|
= note: the `expr` fragment specifier forces the metavariable's content to be an expression
= note: this error originates in the macro `funny` (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to 2 previous errors
error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0425`.
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,20 @@
macro_rules! mac1 {
($eval:expr) => {
let mut $eval = ();
//~^ ERROR `mut` must be followed by a named binding
//~^ ERROR expected identifier, found expression `does_not_exist!()`
};
}

macro_rules! mac2 {
($eval:pat) => {
let mut $eval = ();
//~^ ERROR `mut` must be followed by a named binding
//~| ERROR expected identifier, found `does_not_exist!()`
//~^ ERROR expected identifier, found `does_not_exist!()`
//~| ERROR `mut` must be followed by a named binding
};
}

fn foo() {
mac1! { does_not_exist!() }
//~^ ERROR cannot find macro `does_not_exist` in this scope
mac2! { does_not_exist!() }
//~^ ERROR cannot find macro `does_not_exist` in this scope
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
error: `mut` must be followed by a named binding
--> $DIR/issue-65122-mac-invoc-in-mut-patterns.rs:6:13
error: expected identifier, found expression `does_not_exist!()`
--> $DIR/issue-65122-mac-invoc-in-mut-patterns.rs:6:17
|
LL | let mut $eval = ();
| ^^^^ help: remove the `mut` prefix
| ^^^^^ expected identifier
...
LL | mac1! { does_not_exist!() }
| --------------------------- in this macro invocation
|
= note: `mut` may be followed by `variable` and `variable @ pattern`
= note: this error originates in the macro `mac1` (in Nightly builds, run with -Z macro-backtrace for more info)

error: expected identifier, found `does_not_exist!()`
Expand All @@ -34,16 +33,10 @@ LL | mac2! { does_not_exist!() }
= note: this error originates in the macro `mac2` (in Nightly builds, run with -Z macro-backtrace for more info)

error: cannot find macro `does_not_exist` in this scope
--> $DIR/issue-65122-mac-invoc-in-mut-patterns.rs:22:13
--> $DIR/issue-65122-mac-invoc-in-mut-patterns.rs:21:13
|
LL | mac2! { does_not_exist!() }
| ^^^^^^^^^^^^^^

error: cannot find macro `does_not_exist` in this scope
--> $DIR/issue-65122-mac-invoc-in-mut-patterns.rs:20:13
|
LL | mac1! { does_not_exist!() }
| ^^^^^^^^^^^^^^

error: aborting due to 5 previous errors
error: aborting due to 4 previous errors

8 changes: 3 additions & 5 deletions tests/ui/pattern/issue-92074-macro-ice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,19 @@ fn get_usize() -> usize {
}

macro_rules! force_expr {
($e:expr) => { $e }
($e:expr) => { $e } //~ ERROR expected pattern, found expression `Vec :: new()`
}

macro_rules! force_pat {
($a:expr, $b:expr) => { $a..=$b }
($a:expr, $b:expr) => { $a..=$b } //~ ERROR expected pattern, found expression `get_usize()`
}

macro_rules! make_vec {
() => { force_expr!(Vec::new()) } //~ ERROR arbitrary expressions aren't allowed
() => { force_expr!(Vec::new()) }
}

macro_rules! make_pat {
() => { force_pat!(get_usize(), get_usize()) }
//~^ ERROR arbitrary expressions aren't allowed
//~| ERROR arbitrary expressions aren't allowed
}

#[allow(unreachable_code)]
Expand Down
Loading

0 comments on commit 74a18a0

Please sign in to comment.