more reuse in block parsing & improve diagnostics.

This commit is contained in:
Mazdak Farrokhzad 2020-03-05 05:49:30 +01:00
parent 883e90dd81
commit 8ee220c447
9 changed files with 98 additions and 20 deletions

View File

@ -535,6 +535,16 @@ impl Token {
false
}
// Is the token an interpolated block (`$b:block`)?
pub fn is_whole_block(&self) -> bool {
if let Interpolated(ref nt) = self.kind {
if let NtBlock(..) = **nt {
return true;
}
}
false
}
/// Returns `true` if the token is either the `mut` or `const` keyword.
pub fn is_mutability(&self) -> bool {
self.is_keyword(kw::Mut) || self.is_keyword(kw::Const)

View File

@ -1077,7 +1077,7 @@ impl<'a> Parser<'a> {
self.parse_for_expr(label, lo, attrs)
} else if self.eat_keyword(kw::Loop) {
self.parse_loop_expr(label, lo, attrs)
} else if self.check(&token::OpenDelim(token::Brace)) {
} else if self.check(&token::OpenDelim(token::Brace)) || self.token.is_whole_block() {
self.parse_block_expr(label, lo, BlockCheckMode::Default, attrs)
} else {
let msg = "expected `while`, `for`, `loop` or `{` after a label";
@ -1361,18 +1361,20 @@ impl<'a> Parser<'a> {
opt_label: Option<Label>,
lo: Span,
blk_mode: BlockCheckMode,
outer_attrs: AttrVec,
mut attrs: AttrVec,
) -> PResult<'a, P<Expr>> {
if let Some(label) = opt_label {
self.sess.gated_spans.gate(sym::label_break_value, label.ident.span);
}
self.expect(&token::OpenDelim(token::Brace))?;
if self.token.is_whole_block() {
self.struct_span_err(self.token.span, "cannot use a `block` macro fragment here")
.span_label(lo.to(self.token.span), "the `block` fragment is within this context")
.emit();
}
let mut attrs = outer_attrs;
attrs.extend(self.parse_inner_attributes()?);
let blk = self.parse_block_tail(lo, blk_mode)?;
let (inner_attrs, blk) = self.parse_block_common(lo, blk_mode)?;
attrs.extend(inner_attrs);
Ok(self.mk_expr(blk.span, ExprKind::Block(blk, opt_label), attrs))
}

View File

@ -240,13 +240,11 @@ impl<'a> Parser<'a> {
pub fn parse_block(&mut self) -> PResult<'a, P<Block>> {
maybe_whole!(self, NtBlock, |x| x);
let lo = self.token.span;
if !self.eat(&token::OpenDelim(token::Brace)) {
return self.error_block_no_opening_brace();
}
self.parse_block_tail(lo, BlockCheckMode::Default)
self.parse_block_tail(self.prev_token.span, BlockCheckMode::Default)
}
fn error_block_no_opening_brace<T>(&mut self) -> PResult<'a, T> {
@ -301,15 +299,22 @@ impl<'a> Parser<'a> {
pub(super) fn parse_inner_attrs_and_block(
&mut self,
) -> PResult<'a, (Vec<Attribute>, P<Block>)> {
maybe_whole!(self, NtBlock, |x| (Vec::new(), x));
self.parse_block_common(self.token.span, BlockCheckMode::Default)
}
let lo = self.token.span;
/// Parses a block. Inner attributes are allowed.
pub(super) fn parse_block_common(
&mut self,
lo: Span,
blk_mode: BlockCheckMode,
) -> PResult<'a, (Vec<Attribute>, P<Block>)> {
maybe_whole!(self, NtBlock, |x| (Vec::new(), x));
if !self.eat(&token::OpenDelim(token::Brace)) {
return self.error_block_no_opening_brace();
}
Ok((self.parse_inner_attributes()?, self.parse_block_tail(lo, BlockCheckMode::Default)?))
Ok((self.parse_inner_attributes()?, self.parse_block_tail(lo, blk_mode)?))
}
/// Parses the rest of a block expression or function body.

View File

@ -2,7 +2,10 @@ error: expected `{`, found `'b`
--> $DIR/label_break_value_illegal_uses.rs:6:12
|
LL | unsafe 'b: {}
| ^^ expected `{`
| ^^----
| |
| expected `{`
| help: try placing this code inside a block: `{ 'b: {} }`
error: expected `{`, found `'b`
--> $DIR/label_break_value_illegal_uses.rs:10:13

View File

@ -0,0 +1,15 @@
#![feature(label_break_value)]
fn main() {}
macro_rules! m {
($b:block) => {
'lab: $b; //~ ERROR cannot use a `block` macro fragment here
unsafe $b; //~ ERROR cannot use a `block` macro fragment here
|x: u8| -> () $b; //~ ERROR cannot use a `block` macro fragment here
}
}
fn foo() {
m!({});
}

View File

@ -0,0 +1,39 @@
error: cannot use a `block` macro fragment here
--> $DIR/bad-interpolated-block.rs:7:15
|
LL | 'lab: $b;
| ------^^
| |
| the `block` fragment is within this context
...
LL | m!({});
| ------- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: cannot use a `block` macro fragment here
--> $DIR/bad-interpolated-block.rs:8:16
|
LL | unsafe $b;
| -------^^
| |
| the `block` fragment is within this context
...
LL | m!({});
| ------- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: cannot use a `block` macro fragment here
--> $DIR/bad-interpolated-block.rs:9:23
|
LL | |x: u8| -> () $b;
| ^^ the `block` fragment is within this context
...
LL | m!({});
| ------- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 3 previous errors

View File

@ -3,5 +3,5 @@
fn main() {
let x = || -> i32 22;
//~^ ERROR expected one of `!`, `(`, `+`, `::`, `<`, or `{`, found `22`
//~^ ERROR expected `{`, found `22`
}

View File

@ -1,8 +1,11 @@
error: expected one of `!`, `(`, `+`, `::`, `<`, or `{`, found `22`
error: expected `{`, found `22`
--> $DIR/closure-return-syntax.rs:5:23
|
LL | let x = || -> i32 22;
| ^^ expected one of `!`, `(`, `+`, `::`, `<`, or `{`
| ^^-
| |
| expected `{`
| help: try placing this code inside a block: `{ 22; }`
error: aborting due to previous error

View File

@ -1,10 +1,11 @@
error: expected `{`, found `std`
--> $DIR/unsafe-block-without-braces.rs:3:9
|
LL | unsafe //{
| - expected `{`
LL | std::mem::transmute::<f32, u32>(1.0);
| ^^^ unexpected token
| ^^^----------------------------------
| |
| expected `{`
| help: try placing this code inside a block: `{ std::mem::transmute::<f32, u32>(1.0); }`
error: aborting due to previous error