Skip to content

Point at type ascription before macro invocation on expansion parse error #62816

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 4, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/libsyntax/ast.rs
Original file line number Diff line number Diff line change
@@ -1303,6 +1303,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)]
2 changes: 2 additions & 0 deletions src/libsyntax/ext/base.rs
Original file line number Diff line number Diff line change
@@ -713,6 +713,7 @@ pub struct ExpansionData {
pub depth: usize,
pub module: Rc<ModuleData>,
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(),
9 changes: 7 additions & 2 deletions src/libsyntax/ext/expand.rs
Original file line number Diff line number Diff line change
@@ -517,16 +517,21 @@ 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}",
kind = fragment_kind.name(), path = mac.node.path);
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!()
}
1 change: 1 addition & 0 deletions src/libsyntax/ext/placeholders.rs
Original file line number Diff line number Diff line change
@@ -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,
})
}

1 change: 1 addition & 0 deletions src/libsyntax/ext/tt/macro_rules.rs
Original file line number Diff line number Diff line change
@@ -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.
2 changes: 1 addition & 1 deletion src/libsyntax/mut_visit.rs
Original file line number Diff line number Diff line change
@@ -530,7 +530,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) {
let Mac_ { path, delim: _, tts } = node;
let Mac_ { path, delim: _, tts, .. } = node;
vis.visit_path(path);
vis.visit_tts(tts);
vis.visit_span(span);
42 changes: 36 additions & 6 deletions src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
@@ -1414,7 +1414,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.
@@ -2245,7 +2250,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;
@@ -3971,7 +3981,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 => {
@@ -4417,7 +4432,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())))
@@ -7550,7 +7570,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));
@@ -7600,7 +7625,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)
}
1 change: 1 addition & 0 deletions src/libsyntax_ext/assert.rs
Original file line number Diff line number Diff line change
@@ -38,6 +38,7 @@ pub fn expand_assert<'cx>(
))
}).into(),
delim: MacDelimiter::Parenthesis,
prior_type_ascription: None,
};
let if_expr = cx.expr_if(
sp,
11 changes: 7 additions & 4 deletions src/test/ui/type/ascription/issue-47666.stderr
Original file line number Diff line number Diff line change
@@ -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: `<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)

error: aborting due to previous error