1
Fork 0

Emit an error instead of reconstructing token stream.

This commit is contained in:
Camille GILLOT 2022-08-08 19:17:37 +02:00
parent 8823634db8
commit cb5ea8d0b6
4 changed files with 58 additions and 59 deletions

View file

@ -7,6 +7,7 @@ use rustc_ast::visit::Visitor;
use rustc_ast::NodeId; use rustc_ast::NodeId;
use rustc_ast::{mut_visit, visit}; use rustc_ast::{mut_visit, visit};
use rustc_ast::{Attribute, HasAttrs, HasTokens}; use rustc_ast::{Attribute, HasAttrs, HasTokens};
use rustc_errors::PResult;
use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_expand::config::StripUnconfigured; use rustc_expand::config::StripUnconfigured;
use rustc_expand::configure; use rustc_expand::configure;
@ -144,33 +145,34 @@ impl CfgEval<'_, '_> {
// the location of `#[cfg]` and `#[cfg_attr]` in the token stream. The tokenization // the location of `#[cfg]` and `#[cfg_attr]` in the token stream. The tokenization
// process is lossless, so this process is invisible to proc-macros. // process is lossless, so this process is invisible to proc-macros.
let parse_annotatable_with: fn(&mut Parser<'_>) -> _ = match annotatable { let parse_annotatable_with: for<'a> fn(&mut Parser<'a>) -> PResult<'a, _> =
Annotatable::Item(_) => { match annotatable {
|parser| Annotatable::Item(parser.parse_item(ForceCollect::Yes).unwrap().unwrap()) Annotatable::Item(_) => {
} |parser| Ok(Annotatable::Item(parser.parse_item(ForceCollect::Yes)?.unwrap()))
Annotatable::TraitItem(_) => |parser| { }
Annotatable::TraitItem( Annotatable::TraitItem(_) => |parser| {
parser.parse_trait_item(ForceCollect::Yes).unwrap().unwrap().unwrap(), Ok(Annotatable::TraitItem(
) parser.parse_trait_item(ForceCollect::Yes)?.unwrap().unwrap(),
}, ))
Annotatable::ImplItem(_) => |parser| { },
Annotatable::ImplItem( Annotatable::ImplItem(_) => |parser| {
parser.parse_impl_item(ForceCollect::Yes).unwrap().unwrap().unwrap(), Ok(Annotatable::ImplItem(
) parser.parse_impl_item(ForceCollect::Yes)?.unwrap().unwrap(),
}, ))
Annotatable::ForeignItem(_) => |parser| { },
Annotatable::ForeignItem( Annotatable::ForeignItem(_) => |parser| {
parser.parse_foreign_item(ForceCollect::Yes).unwrap().unwrap().unwrap(), Ok(Annotatable::ForeignItem(
) parser.parse_foreign_item(ForceCollect::Yes)?.unwrap().unwrap(),
}, ))
Annotatable::Stmt(_) => |parser| { },
Annotatable::Stmt(P(parser.parse_stmt(ForceCollect::Yes).unwrap().unwrap())) Annotatable::Stmt(_) => |parser| {
}, Ok(Annotatable::Stmt(P(parser.parse_stmt(ForceCollect::Yes)?.unwrap())))
Annotatable::Expr(_) => { },
|parser| Annotatable::Expr(parser.parse_expr_force_collect().unwrap()) Annotatable::Expr(_) => {
} |parser| Ok(Annotatable::Expr(parser.parse_expr_force_collect()?))
_ => unreachable!(), }
}; _ => unreachable!(),
};
// 'Flatten' all nonterminals (i.e. `TokenKind::Interpolated`) // 'Flatten' all nonterminals (i.e. `TokenKind::Interpolated`)
// to `None`-delimited groups containing the corresponding tokens. This // to `None`-delimited groups containing the corresponding tokens. This
@ -193,7 +195,13 @@ impl CfgEval<'_, '_> {
let mut parser = let mut parser =
rustc_parse::stream_to_parser(&self.cfg.sess.parse_sess, orig_tokens, None); rustc_parse::stream_to_parser(&self.cfg.sess.parse_sess, orig_tokens, None);
parser.capture_cfg = true; parser.capture_cfg = true;
annotatable = parse_annotatable_with(&mut parser); match parse_annotatable_with(&mut parser) {
Ok(a) => annotatable = a,
Err(mut err) => {
err.emit();
return Some(annotatable);
}
}
// Now that we have our re-parsed `AttrTokenStream`, recursively configuring // Now that we have our re-parsed `AttrTokenStream`, recursively configuring
// our attribute target will correctly the tokens as well. // our attribute target will correctly the tokens as well.

View file

@ -442,38 +442,22 @@ fn make_token_stream(
} }
token_and_spacing = iter.next(); token_and_spacing = iter.next();
} }
while let Some(FrameData { open_delim_sp, mut inner }) = stack.pop() { let mut final_buf = stack.pop().expect("Missing final buf!");
// A former macro expansion could give us malformed tokens. if break_last_token {
// In that case, manually close all open delimitors so downstream users let last_token = final_buf.inner.pop().unwrap();
// don't ICE on them. if let AttrTokenTree::Token(last_token, spacing) = last_token {
if let Some((delim, open_sp)) = open_delim_sp { let unglued_first = last_token.kind.break_two_token_op().unwrap().0;
let dspan = DelimSpan::from_pair(open_sp, rustc_span::DUMMY_SP);
let stream = AttrTokenStream::new(inner); // An 'unglued' token is always two ASCII characters
let delimited = AttrTokenTree::Delimited(dspan, delim, stream); let mut first_span = last_token.span.shrink_to_lo();
stack first_span = first_span.with_hi(first_span.lo() + rustc_span::BytePos(1));
.last_mut()
.unwrap_or_else(|| panic!("Bottom token frame is missing for recovered token")) final_buf
.inner .inner
.push(delimited); .push(AttrTokenTree::Token(Token::new(unglued_first, first_span), spacing));
} else { } else {
if break_last_token { panic!("Unexpected last token {:?}", last_token)
let last_token = inner.pop().unwrap();
if let AttrTokenTree::Token(last_token, spacing) = last_token {
let unglued_first = last_token.kind.break_two_token_op().unwrap().0;
// An 'unglued' token is always two ASCII characters
let mut first_span = last_token.span.shrink_to_lo();
first_span = first_span.with_hi(first_span.lo() + rustc_span::BytePos(1));
inner
.push(AttrTokenTree::Token(Token::new(unglued_first, first_span), spacing));
} else {
panic!("Unexpected last token {:?}", last_token)
}
}
assert!(stack.is_empty(), "Stack should be empty: stack={:?}", stack);
return AttrTokenStream::new(inner);
} }
} }
panic!("Missing final buf!") AttrTokenStream::new(final_buf.inner)
} }

View file

@ -13,5 +13,6 @@ macro_rules! values {
//~| ERROR macro expansion ignores token `(String)` and any following //~| ERROR macro expansion ignores token `(String)` and any following
values!(STRING(1) as (String) => cfg(test),); values!(STRING(1) as (String) => cfg(test),);
//~^ ERROR expected one of `!` or `::`, found `<eof>`
fn main() {} fn main() {}

View file

@ -20,5 +20,11 @@ LL | values!(STRING(1) as (String) => cfg(test),);
| |
= note: the usage of `values!` is likely invalid in item context = note: the usage of `values!` is likely invalid in item context
error: aborting due to 2 previous errors error: expected one of `!` or `::`, found `<eof>`
--> $DIR/syntax-error-recovery.rs:15:9
|
LL | values!(STRING(1) as (String) => cfg(test),);
| ^^^^^^ expected one of `!` or `::`
error: aborting due to 3 previous errors