11
11
use { ast, attr} ;
12
12
use syntax_pos:: { Span , DUMMY_SP } ;
13
13
use edition:: Edition ;
14
+ use errors:: FatalError ;
14
15
use ext:: base:: { DummyResult , ExtCtxt , MacResult , SyntaxExtension } ;
15
16
use ext:: base:: { NormalTT , TTMacroExpander } ;
16
17
use ext:: expand:: { AstFragment , AstFragmentKind } ;
@@ -44,15 +45,34 @@ pub struct ParserAnyMacro<'a> {
44
45
/// Span of the expansion site of the macro this parser is for
45
46
site_span : Span ,
46
47
/// The ident of the macro we're parsing
47
- macro_ident : ast:: Ident
48
+ macro_ident : ast:: Ident ,
49
+ arm_span : Span ,
48
50
}
49
51
50
52
impl < ' a > ParserAnyMacro < ' a > {
51
53
pub fn make ( mut self : Box < ParserAnyMacro < ' a > > , kind : AstFragmentKind ) -> AstFragment {
52
- let ParserAnyMacro { site_span, macro_ident, ref mut parser } = * self ;
54
+ let ParserAnyMacro { site_span, macro_ident, ref mut parser, arm_span } = * self ;
53
55
let fragment = panictry ! ( parser. parse_ast_fragment( kind, true ) . map_err( |mut e| {
56
+ if parser. token == token:: Eof && e. message( ) . ends_with( ", found `<eof>`" ) {
57
+ if !e. span. is_dummy( ) { // early end of macro arm (#52866)
58
+ e. replace_span_with( parser. sess. source_map( ) . next_point( parser. span) ) ;
59
+ }
60
+ let msg = & e. message[ 0 ] ;
61
+ e. message[ 0 ] = (
62
+ format!(
63
+ "macro expansion ends with an incomplete expression: {}" ,
64
+ msg. 0 . replace( ", found `<eof>`" , "" ) ,
65
+ ) ,
66
+ msg. 1 ,
67
+ ) ;
68
+ }
54
69
if e. span. is_dummy( ) { // Get around lack of span in error (#30128)
55
- e. set_span( site_span) ;
70
+ e. replace_span_with( site_span) ;
71
+ if parser. sess. source_map( ) . span_to_filename( arm_span) . is_real( ) {
72
+ e. span_label( arm_span, "in this macro arm" ) ;
73
+ }
74
+ } else if !parser. sess. source_map( ) . span_to_filename( parser. span) . is_real( ) {
75
+ e. span_label( site_span, "in this macro invocation" ) ;
56
76
}
57
77
e
58
78
} ) ) ;
@@ -120,6 +140,7 @@ fn generic_extension<'cx>(cx: &'cx mut ExtCtxt,
120
140
// Which arm's failure should we report? (the one furthest along)
121
141
let mut best_fail_spot = DUMMY_SP ;
122
142
let mut best_fail_tok = None ;
143
+ let mut best_fail_text = None ;
123
144
124
145
for ( i, lhs) in lhses. iter ( ) . enumerate ( ) { // try each arm's matchers
125
146
let lhs_tt = match * lhs {
@@ -134,6 +155,7 @@ fn generic_extension<'cx>(cx: &'cx mut ExtCtxt,
134
155
quoted:: TokenTree :: Delimited ( _, ref delimed) => delimed. tts . clone ( ) ,
135
156
_ => cx. span_bug ( sp, "malformed macro rhs" ) ,
136
157
} ;
158
+ let arm_span = rhses[ i] . span ( ) ;
137
159
138
160
let rhs_spans = rhs. iter ( ) . map ( |t| t. span ( ) ) . collect :: < Vec < _ > > ( ) ;
139
161
// rhs has holes ( `$id` and `$(...)` that need filled)
@@ -172,12 +194,14 @@ fn generic_extension<'cx>(cx: &'cx mut ExtCtxt,
172
194
// so we can print a useful error message if the parse of the expanded
173
195
// macro leaves unparsed tokens.
174
196
site_span : sp,
175
- macro_ident : name
197
+ macro_ident : name,
198
+ arm_span,
176
199
} )
177
200
}
178
- Failure ( sp, tok) => if sp. lo ( ) >= best_fail_spot. lo ( ) {
201
+ Failure ( sp, tok, t ) => if sp. lo ( ) >= best_fail_spot. lo ( ) {
179
202
best_fail_spot = sp;
180
203
best_fail_tok = Some ( tok) ;
204
+ best_fail_text = Some ( t) ;
181
205
} ,
182
206
Error ( err_sp, ref msg) => {
183
207
cx. span_fatal ( err_sp. substitute_dummy ( sp) , & msg[ ..] )
@@ -188,7 +212,7 @@ fn generic_extension<'cx>(cx: &'cx mut ExtCtxt,
188
212
let best_fail_msg = parse_failure_msg ( best_fail_tok. expect ( "ran no matchers" ) ) ;
189
213
let span = best_fail_spot. substitute_dummy ( sp) ;
190
214
let mut err = cx. struct_span_err ( span, & best_fail_msg) ;
191
- err. span_label ( span, best_fail_msg) ;
215
+ err. span_label ( span, best_fail_text . unwrap_or ( best_fail_msg) ) ;
192
216
if let Some ( sp) = def_span {
193
217
if cx. source_map ( ) . span_to_filename ( sp) . is_real ( ) && !sp. is_dummy ( ) {
194
218
err. span_label ( cx. source_map ( ) . def_span ( sp) , "when calling this macro" ) ;
@@ -268,9 +292,13 @@ pub fn compile(sess: &ParseSess, features: &Features, def: &ast::Item, edition:
268
292
269
293
let argument_map = match parse ( sess, body. stream ( ) , & argument_gram, None , true ) {
270
294
Success ( m) => m,
271
- Failure ( sp, tok) => {
295
+ Failure ( sp, tok, t ) => {
272
296
let s = parse_failure_msg ( tok) ;
273
- sess. span_diagnostic . span_fatal ( sp. substitute_dummy ( def. span ) , & s) . raise ( ) ;
297
+ let sp = sp. substitute_dummy ( def. span ) ;
298
+ let mut err = sess. span_diagnostic . struct_span_fatal ( sp, & s) ;
299
+ err. span_label ( sp, t) ;
300
+ err. emit ( ) ;
301
+ FatalError . raise ( ) ;
274
302
}
275
303
Error ( sp, s) => {
276
304
sess. span_diagnostic . span_fatal ( sp. substitute_dummy ( def. span ) , & s) . raise ( ) ;
0 commit comments