Auto merge of #62816 - estebank:type-ascription-macros, r=petrochenkov

Point at type ascription before macro invocation on expansion parse error

Fix https://github.com/rust-lang/rust/issues/47666. Follow up to https://github.com/rust-lang/rust/pull/62791.

r? @petrochenkov
This commit is contained in:
bors 2019-08-04 16:19:04 +00:00
commit f01b9f803b
9 changed files with 57 additions and 13 deletions

View File

@ -1306,6 +1306,7 @@ pub struct Mac_ {
pub path: Path, pub path: Path,
pub delim: MacDelimiter, pub delim: MacDelimiter,
pub tts: TokenStream, pub tts: TokenStream,
pub prior_type_ascription: Option<(Span, bool)>,
} }
#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)] #[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)]

View File

@ -713,6 +713,7 @@ pub struct ExpansionData {
pub depth: usize, pub depth: usize,
pub module: Rc<ModuleData>, pub module: Rc<ModuleData>,
pub directory_ownership: DirectoryOwnership, pub directory_ownership: DirectoryOwnership,
pub prior_type_ascription: Option<(Span, bool)>,
} }
/// One of these is made during expansion and incrementally updated as we go; /// One of these is made during expansion and incrementally updated as we go;
@ -743,6 +744,7 @@ impl<'a> ExtCtxt<'a> {
depth: 0, depth: 0,
module: Rc::new(ModuleData { mod_path: Vec::new(), directory: PathBuf::new() }), module: Rc::new(ModuleData { mod_path: Vec::new(), directory: PathBuf::new() }),
directory_ownership: DirectoryOwnership::Owned { relative: None }, directory_ownership: DirectoryOwnership::Owned { relative: None },
prior_type_ascription: None,
}, },
expansions: FxHashMap::default(), expansions: FxHashMap::default(),
allow_derive_markers: [sym::rustc_attrs, sym::structural_match][..].into(), allow_derive_markers: [sym::rustc_attrs, sym::structural_match][..].into(),

View File

@ -517,8 +517,11 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
result result
} }
SyntaxExtensionKind::LegacyBang(expander) => { SyntaxExtensionKind::LegacyBang(expander) => {
let prev = self.cx.current_expansion.prior_type_ascription;
self.cx.current_expansion.prior_type_ascription =
mac.node.prior_type_ascription;
let tok_result = expander.expand(self.cx, span, mac.node.stream()); let tok_result = expander.expand(self.cx, span, mac.node.stream());
if let Some(result) = fragment_kind.make_from(tok_result) { let result = if let Some(result) = fragment_kind.make_from(tok_result) {
result result
} else { } else {
let msg = format!("non-{kind} macro in {kind} position: {path}", let msg = format!("non-{kind} macro in {kind} position: {path}",
@ -526,7 +529,9 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
self.cx.span_err(span, &msg); self.cx.span_err(span, &msg);
self.cx.trace_macros_diag(); self.cx.trace_macros_diag();
fragment_kind.dummy(span) fragment_kind.dummy(span)
} };
self.cx.current_expansion.prior_type_ascription = prev;
result
} }
_ => unreachable!() _ => unreachable!()
} }

View File

@ -18,6 +18,7 @@ pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId) -> AstFragment {
path: ast::Path { span: DUMMY_SP, segments: Vec::new() }, path: ast::Path { span: DUMMY_SP, segments: Vec::new() },
tts: TokenStream::empty().into(), tts: TokenStream::empty().into(),
delim: ast::MacDelimiter::Brace, delim: ast::MacDelimiter::Brace,
prior_type_ascription: None,
}) })
} }

View File

@ -173,6 +173,7 @@ fn generic_extension<'cx>(
let mut p = Parser::new(cx.parse_sess(), tts, Some(directory), true, false, None); let mut p = Parser::new(cx.parse_sess(), tts, Some(directory), true, false, None);
p.root_module_name = p.root_module_name =
cx.current_expansion.module.mod_path.last().map(|id| id.as_str().to_string()); cx.current_expansion.module.mod_path.last().map(|id| id.as_str().to_string());
p.last_type_ascription = cx.current_expansion.prior_type_ascription;
p.process_potential_macro_variable(); p.process_potential_macro_variable();
// Let the context choose how to interpret the result. // Let the context choose how to interpret the result.

View File

@ -533,7 +533,7 @@ pub fn noop_visit_attribute<T: MutVisitor>(attr: &mut Attribute, vis: &mut T) {
} }
pub fn noop_visit_mac<T: MutVisitor>(Spanned { node, span }: &mut Mac, vis: &mut T) { pub fn noop_visit_mac<T: MutVisitor>(Spanned { node, span }: &mut Mac, vis: &mut T) {
let Mac_ { path, delim: _, tts } = node; let Mac_ { path, delim: _, tts, .. } = node;
vis.visit_path(path); vis.visit_path(path);
vis.visit_tts(tts); vis.visit_tts(tts);
vis.visit_span(span); vis.visit_span(span);

View File

@ -1415,7 +1415,12 @@ impl<'a> Parser<'a> {
if self.eat(&token::Not) { if self.eat(&token::Not) {
// Macro invocation in type position // Macro invocation in type position
let (delim, tts) = self.expect_delimited_token_tree()?; let (delim, tts) = self.expect_delimited_token_tree()?;
let node = Mac_ { path, tts, delim }; let node = Mac_ {
path,
tts,
delim,
prior_type_ascription: self.last_type_ascription,
};
TyKind::Mac(respan(lo.to(self.prev_span), node)) TyKind::Mac(respan(lo.to(self.prev_span), node))
} else { } else {
// Just a type path or bound list (trait object type) starting with a trait. // Just a type path or bound list (trait object type) starting with a trait.
@ -2246,7 +2251,12 @@ impl<'a> Parser<'a> {
// MACRO INVOCATION expression // MACRO INVOCATION expression
let (delim, tts) = self.expect_delimited_token_tree()?; let (delim, tts) = self.expect_delimited_token_tree()?;
hi = self.prev_span; hi = self.prev_span;
ex = ExprKind::Mac(respan(lo.to(hi), Mac_ { path, tts, delim })); ex = ExprKind::Mac(respan(lo.to(hi), Mac_ {
path,
tts,
delim,
prior_type_ascription: self.last_type_ascription,
}));
} else if self.check(&token::OpenDelim(token::Brace)) { } else if self.check(&token::OpenDelim(token::Brace)) {
if let Some(expr) = self.maybe_parse_struct_expr(lo, &path, &attrs) { if let Some(expr) = self.maybe_parse_struct_expr(lo, &path, &attrs) {
return expr; return expr;
@ -3963,7 +3973,12 @@ impl<'a> Parser<'a> {
// Parse macro invocation // Parse macro invocation
self.bump(); self.bump();
let (delim, tts) = self.expect_delimited_token_tree()?; let (delim, tts) = self.expect_delimited_token_tree()?;
let mac = respan(lo.to(self.prev_span), Mac_ { path, tts, delim }); let mac = respan(lo.to(self.prev_span), Mac_ {
path,
tts,
delim,
prior_type_ascription: self.last_type_ascription,
});
pat = PatKind::Mac(mac); pat = PatKind::Mac(mac);
} }
token::DotDotDot | token::DotDotEq | token::DotDot => { token::DotDotDot | token::DotDotEq | token::DotDot => {
@ -4403,7 +4418,12 @@ impl<'a> Parser<'a> {
MacStmtStyle::NoBraces MacStmtStyle::NoBraces
}; };
let mac = respan(lo.to(hi), Mac_ { path, tts, delim }); let mac = respan(lo.to(hi), Mac_ {
path,
tts,
delim,
prior_type_ascription: self.last_type_ascription,
});
let node = if delim == MacDelimiter::Brace || let node = if delim == MacDelimiter::Brace ||
self.token == token::Semi || self.token == token::Eof { self.token == token::Semi || self.token == token::Eof {
StmtKind::Mac(P((mac, style, attrs.into()))) StmtKind::Mac(P((mac, style, attrs.into())))
@ -7518,7 +7538,12 @@ impl<'a> Parser<'a> {
} }
let hi = self.prev_span; let hi = self.prev_span;
let mac = respan(mac_lo.to(hi), Mac_ { path, tts, delim }); let mac = respan(mac_lo.to(hi), Mac_ {
path,
tts,
delim,
prior_type_ascription: self.last_type_ascription,
});
let item = let item =
self.mk_item(lo.to(hi), Ident::invalid(), ItemKind::Mac(mac), visibility, attrs); self.mk_item(lo.to(hi), Ident::invalid(), ItemKind::Mac(mac), visibility, attrs);
return Ok(Some(item)); return Ok(Some(item));
@ -7568,7 +7593,12 @@ impl<'a> Parser<'a> {
self.expect(&token::Semi)?; self.expect(&token::Semi)?;
} }
Ok(Some(respan(lo.to(self.prev_span), Mac_ { path, tts, delim }))) Ok(Some(respan(lo.to(self.prev_span), Mac_ {
path,
tts,
delim,
prior_type_ascription: self.last_type_ascription,
})))
} else { } else {
Ok(None) Ok(None)
} }

View File

@ -37,6 +37,7 @@ pub fn expand_assert<'cx>(
)) ))
}).into(), }).into(),
delim: MacDelimiter::Parenthesis, delim: MacDelimiter::Parenthesis,
prior_type_ascription: None,
}; };
let if_expr = cx.expr_if( let if_expr = cx.expr_if(
sp, sp,

View File

@ -2,11 +2,14 @@ error: expected type, found reserved keyword `box`
--> $DIR/issue-47666.rs:2:25 --> $DIR/issue-47666.rs:2:25
| |
LL | let _ = Option:Some(vec![0, 1]); LL | let _ = Option:Some(vec![0, 1]);
| ^^^^^^^^^^ | - ^^^^^^^^^^
| | | | |
| expected type | | expected type
| in this macro invocation | | in this macro invocation
| help: maybe write a path separator here: `::`
| |
= note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>`
= note: for more information, see https://github.com/rust-lang/rust/issues/23416
= note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error: aborting due to previous error error: aborting due to previous error