mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-01 15:01:51 +00:00
Improve handling of spans around macro result parse errors
Fixes #81543 After we expand a macro, we try to parse the resulting tokens as a AST node. This commit makes several improvements to how we handle spans when an error occurs: * Only ovewrite the original `Span` if it's a dummy span. This preserves a more-specific span if one is available. * Use `self.prev_token` instead of `self.token` when emitting an error message after encountering EOF, since an EOF token always has a dummy span * Make `SourceMap::next_point` leave dummy spans unused. A dummy span does not have a logical 'next point', since it's a zero-length span. Re-using the span span preserves its 'dummy-ness' for other checks
This commit is contained in:
parent
04caa632dd
commit
6c14aad58e
@ -896,7 +896,9 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||
fragment
|
||||
}
|
||||
Err(mut err) => {
|
||||
err.set_span(span);
|
||||
if err.span.is_dummy() {
|
||||
err.set_span(span);
|
||||
}
|
||||
annotate_err_with_kind(&mut err, kind, span);
|
||||
err.emit();
|
||||
self.cx.trace_macros_diag();
|
||||
|
@ -1104,7 +1104,7 @@ impl<'a> Parser<'a> {
|
||||
let (prev_sp, sp) = match (&self.token.kind, self.subparser_name) {
|
||||
// Point at the end of the macro call when reaching end of macro arguments.
|
||||
(token::Eof, Some(_)) => {
|
||||
let sp = self.sess.source_map().next_point(self.token.span);
|
||||
let sp = self.sess.source_map().next_point(self.prev_token.span);
|
||||
(sp, sp)
|
||||
}
|
||||
// We don't want to point at the following span after DUMMY_SP.
|
||||
@ -1721,7 +1721,7 @@ impl<'a> Parser<'a> {
|
||||
pub(super) fn expected_expression_found(&self) -> DiagnosticBuilder<'a> {
|
||||
let (span, msg) = match (&self.token.kind, self.subparser_name) {
|
||||
(&token::Eof, Some(origin)) => {
|
||||
let sp = self.sess.source_map().next_point(self.token.span);
|
||||
let sp = self.sess.source_map().next_point(self.prev_token.span);
|
||||
(sp, format!("expected expression, found end of {}", origin))
|
||||
}
|
||||
_ => (
|
||||
|
@ -799,6 +799,9 @@ impl SourceMap {
|
||||
|
||||
/// Returns a new span representing the next character after the end-point of this span.
|
||||
pub fn next_point(&self, sp: Span) -> Span {
|
||||
if sp.is_dummy() {
|
||||
return sp;
|
||||
}
|
||||
let start_of_next_point = sp.hi().0;
|
||||
|
||||
let width = self.find_width_of_character_at_span(sp.shrink_to_hi(), true);
|
||||
|
14
src/test/ui/proc-macro/issue-81543-item-parse-err.rs
Normal file
14
src/test/ui/proc-macro/issue-81543-item-parse-err.rs
Normal file
@ -0,0 +1,14 @@
|
||||
// aux-build:test-macros.rs
|
||||
|
||||
// Regression test for issue #81543
|
||||
// Tests that we emit a properly spanned error
|
||||
// when the output of a proc-macro cannot be parsed
|
||||
// as the expected AST node kind
|
||||
|
||||
extern crate test_macros;
|
||||
|
||||
test_macros::identity! {
|
||||
fn 32() {} //~ ERROR expected identifier
|
||||
}
|
||||
|
||||
fn main() {}
|
8
src/test/ui/proc-macro/issue-81543-item-parse-err.stderr
Normal file
8
src/test/ui/proc-macro/issue-81543-item-parse-err.stderr
Normal file
@ -0,0 +1,8 @@
|
||||
error: expected identifier, found `32`
|
||||
--> $DIR/issue-81543-item-parse-err.rs:11:8
|
||||
|
|
||||
LL | fn 32() {}
|
||||
| ^^ expected identifier
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -2,7 +2,12 @@ error: expected type, found `'`
|
||||
--> $DIR/lifetimes.rs:7:10
|
||||
|
|
||||
LL | type A = single_quote_alone!();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ this macro call doesn't expand to a type
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| expected type
|
||||
| this macro call doesn't expand to a type
|
||||
|
|
||||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user