diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 246c8f4b91f2d..ea8fa02385512 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1306,6 +1306,7 @@ pub struct Mac_ { pub path: Path, pub delim: MacDelimiter, pub tts: TokenStream, + pub prior_type_ascription: Option<(Span, bool)>, } #[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)] diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index bb7834a133f03..239fe55672e12 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -713,6 +713,7 @@ pub struct ExpansionData { pub depth: usize, pub module: Rc, pub directory_ownership: DirectoryOwnership, + pub prior_type_ascription: Option<(Span, bool)>, } /// One of these is made during expansion and incrementally updated as we go; @@ -743,6 +744,7 @@ impl<'a> ExtCtxt<'a> { depth: 0, module: Rc::new(ModuleData { mod_path: Vec::new(), directory: PathBuf::new() }), directory_ownership: DirectoryOwnership::Owned { relative: None }, + prior_type_ascription: None, }, expansions: FxHashMap::default(), allow_derive_markers: [sym::rustc_attrs, sym::structural_match][..].into(), diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 1e9e16d72f829..3501782423373 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -517,8 +517,11 @@ impl<'a, 'b> MacroExpander<'a, 'b> { result } 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()); - if let Some(result) = fragment_kind.make_from(tok_result) { + let result = if let Some(result) = fragment_kind.make_from(tok_result) { result } else { 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.trace_macros_diag(); fragment_kind.dummy(span) - } + }; + self.cx.current_expansion.prior_type_ascription = prev; + result } _ => unreachable!() } diff --git a/src/libsyntax/ext/placeholders.rs b/src/libsyntax/ext/placeholders.rs index 17d8bf3ab175f..b2b17b0fb2873 100644 --- a/src/libsyntax/ext/placeholders.rs +++ b/src/libsyntax/ext/placeholders.rs @@ -18,6 +18,7 @@ pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId) -> AstFragment { path: ast::Path { span: DUMMY_SP, segments: Vec::new() }, tts: TokenStream::empty().into(), delim: ast::MacDelimiter::Brace, + prior_type_ascription: None, }) } diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index ce695df777572..f825d1e9aae88 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -173,6 +173,7 @@ fn generic_extension<'cx>( let mut p = Parser::new(cx.parse_sess(), tts, Some(directory), true, false, None); p.root_module_name = 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(); // Let the context choose how to interpret the result. diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index 176bcf1959a9d..cbad74e156114 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -533,7 +533,7 @@ pub fn noop_visit_attribute(attr: &mut Attribute, vis: &mut T) { } pub fn noop_visit_mac(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_tts(tts); vis.visit_span(span); diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 880dd6e164982..b14000aeaf390 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1415,7 +1415,12 @@ impl<'a> Parser<'a> { if self.eat(&token::Not) { // Macro invocation in type position 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)) } else { // 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 let (delim, tts) = self.expect_delimited_token_tree()?; 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)) { if let Some(expr) = self.maybe_parse_struct_expr(lo, &path, &attrs) { return expr; @@ -3963,7 +3973,12 @@ impl<'a> Parser<'a> { // Parse macro invocation self.bump(); 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); } token::DotDotDot | token::DotDotEq | token::DotDot => { @@ -4403,7 +4418,12 @@ impl<'a> Parser<'a> { 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 || self.token == token::Semi || self.token == token::Eof { StmtKind::Mac(P((mac, style, attrs.into()))) @@ -7518,7 +7538,12 @@ impl<'a> Parser<'a> { } 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 = self.mk_item(lo.to(hi), Ident::invalid(), ItemKind::Mac(mac), visibility, attrs); return Ok(Some(item)); @@ -7568,7 +7593,12 @@ impl<'a> Parser<'a> { 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 { Ok(None) } diff --git a/src/libsyntax_ext/assert.rs b/src/libsyntax_ext/assert.rs index b10d8fcd357c4..d7571f43eddd0 100644 --- a/src/libsyntax_ext/assert.rs +++ b/src/libsyntax_ext/assert.rs @@ -37,6 +37,7 @@ pub fn expand_assert<'cx>( )) }).into(), delim: MacDelimiter::Parenthesis, + prior_type_ascription: None, }; let if_expr = cx.expr_if( sp, diff --git a/src/test/ui/type/ascription/issue-47666.stderr b/src/test/ui/type/ascription/issue-47666.stderr index 7aa899f795c7d..965bbe5ea41f7 100644 --- a/src/test/ui/type/ascription/issue-47666.stderr +++ b/src/test/ui/type/ascription/issue-47666.stderr @@ -2,11 +2,14 @@ error: expected type, found reserved keyword `box` --> $DIR/issue-47666.rs:2:25 | LL | let _ = Option:Some(vec![0, 1]); - | ^^^^^^^^^^ - | | - | expected type - | in this macro invocation + | - ^^^^^^^^^^ + | | | + | | expected type + | | in this macro invocation + | help: maybe write a path separator here: `::` | + = note: `#![feature(type_ascription)]` lets you annotate an expression with a 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) error: aborting due to previous error