@@ -238,6 +238,56 @@ impl<'a> Resolver<'a> {
238
238
( err, candidates)
239
239
}
240
240
241
+ fn followed_by_brace ( & self , span : Span ) -> ( bool , Option < ( Span , String ) > ) {
242
+ // HACK(estebank): find a better way to figure out that this was a
243
+ // parser issue where a struct literal is being used on an expression
244
+ // where a brace being opened means a block is being started. Look
245
+ // ahead for the next text to see if `span` is followed by a `{`.
246
+ let sm = self . session . source_map ( ) ;
247
+ let mut sp = span;
248
+ loop {
249
+ sp = sm. next_point ( sp) ;
250
+ match sm. span_to_snippet ( sp) {
251
+ Ok ( ref snippet) => {
252
+ if snippet. chars ( ) . any ( |c| { !c. is_whitespace ( ) } ) {
253
+ break ;
254
+ }
255
+ }
256
+ _ => break ,
257
+ }
258
+ }
259
+ let followed_by_brace = match sm. span_to_snippet ( sp) {
260
+ Ok ( ref snippet) if snippet == "{" => true ,
261
+ _ => false ,
262
+ } ;
263
+ // In case this could be a struct literal that needs to be surrounded
264
+ // by parenthesis, find the appropriate span.
265
+ let mut i = 0 ;
266
+ let mut closing_brace = None ;
267
+ loop {
268
+ sp = sm. next_point ( sp) ;
269
+ match sm. span_to_snippet ( sp) {
270
+ Ok ( ref snippet) => {
271
+ if snippet == "}" {
272
+ let sp = span. to ( sp) ;
273
+ if let Ok ( snippet) = sm. span_to_snippet ( sp) {
274
+ closing_brace = Some ( ( sp, snippet) ) ;
275
+ }
276
+ break ;
277
+ }
278
+ }
279
+ _ => break ,
280
+ }
281
+ i += 1 ;
282
+ // The bigger the span, the more likely we're incorrect --
283
+ // bound it to 100 chars long.
284
+ if i > 100 {
285
+ break ;
286
+ }
287
+ }
288
+ return ( followed_by_brace, closing_brace)
289
+ }
290
+
241
291
/// Provides context-dependent help for errors reported by the `smart_resolve_path_fragment`
242
292
/// function.
243
293
/// Returns `true` if able to provide context-dependent help.
@@ -276,6 +326,39 @@ impl<'a> Resolver<'a> {
276
326
_ => false ,
277
327
} ;
278
328
329
+ let mut bad_struct_syntax_suggestion = || {
330
+ let ( followed_by_brace, closing_brace) = self . followed_by_brace ( span) ;
331
+ let mut suggested = false ;
332
+ match source {
333
+ PathSource :: Expr ( Some ( parent) ) => {
334
+ suggested = path_sep ( err, & parent) ;
335
+ }
336
+ PathSource :: Expr ( None ) if followed_by_brace == true => {
337
+ if let Some ( ( sp, snippet) ) = closing_brace {
338
+ err. span_suggestion (
339
+ sp,
340
+ "surround the struct literal with parenthesis" ,
341
+ format ! ( "({})" , snippet) ,
342
+ Applicability :: MaybeIncorrect ,
343
+ ) ;
344
+ } else {
345
+ err. span_label (
346
+ span, // Note the parenthesis surrounding the suggestion below
347
+ format ! ( "did you mean `({} {{ /* fields */ }})`?" , path_str) ,
348
+ ) ;
349
+ }
350
+ suggested = true ;
351
+ } ,
352
+ _ => { }
353
+ }
354
+ if !suggested {
355
+ err. span_label (
356
+ span,
357
+ format ! ( "did you mean `{} {{ /* fields */ }}`?" , path_str) ,
358
+ ) ;
359
+ }
360
+ } ;
361
+
279
362
match ( def, source) {
280
363
( Def :: Macro ( ..) , _) => {
281
364
err. span_suggestion (
@@ -329,87 +412,13 @@ impl<'a> Resolver<'a> {
329
412
) ;
330
413
}
331
414
} else {
332
- // HACK(estebank): find a better way to figure out that this was a
333
- // parser issue where a struct literal is being used on an expression
334
- // where a brace being opened means a block is being started. Look
335
- // ahead for the next text to see if `span` is followed by a `{`.
336
- let sm = self . session . source_map ( ) ;
337
- let mut sp = span;
338
- loop {
339
- sp = sm. next_point ( sp) ;
340
- match sm. span_to_snippet ( sp) {
341
- Ok ( ref snippet) => {
342
- if snippet. chars ( ) . any ( |c| { !c. is_whitespace ( ) } ) {
343
- break ;
344
- }
345
- }
346
- _ => break ,
347
- }
348
- }
349
- let followed_by_brace = match sm. span_to_snippet ( sp) {
350
- Ok ( ref snippet) if snippet == "{" => true ,
351
- _ => false ,
352
- } ;
353
- // In case this could be a struct literal that needs to be surrounded
354
- // by parenthesis, find the appropriate span.
355
- let mut i = 0 ;
356
- let mut closing_brace = None ;
357
- loop {
358
- sp = sm. next_point ( sp) ;
359
- match sm. span_to_snippet ( sp) {
360
- Ok ( ref snippet) => {
361
- if snippet == "}" {
362
- let sp = span. to ( sp) ;
363
- if let Ok ( snippet) = sm. span_to_snippet ( sp) {
364
- closing_brace = Some ( ( sp, snippet) ) ;
365
- }
366
- break ;
367
- }
368
- }
369
- _ => break ,
370
- }
371
- i += 1 ;
372
- // The bigger the span, the more likely we're incorrect --
373
- // bound it to 100 chars long.
374
- if i > 100 {
375
- break ;
376
- }
377
- }
378
- match source {
379
- PathSource :: Expr ( Some ( parent) ) => if !path_sep ( err, & parent) {
380
- err. span_label (
381
- span,
382
- format ! ( "did you mean `{} {{ /* fields */ }}`?" , path_str) ,
383
- ) ;
384
- }
385
- PathSource :: Expr ( None ) if followed_by_brace == true => {
386
- if let Some ( ( sp, snippet) ) = closing_brace {
387
- err. span_suggestion (
388
- sp,
389
- "surround the struct literal with parenthesis" ,
390
- format ! ( "({})" , snippet) ,
391
- Applicability :: MaybeIncorrect ,
392
- ) ;
393
- } else {
394
- err. span_label (
395
- span,
396
- format ! ( "did you mean `({} {{ /* fields */ }})`?" , path_str) ,
397
- ) ;
398
- }
399
- } ,
400
- _ => {
401
- err. span_label (
402
- span,
403
- format ! ( "did you mean `{} {{ /* fields */ }}`?" , path_str) ,
404
- ) ;
405
- } ,
406
- }
415
+ bad_struct_syntax_suggestion ( ) ;
407
416
}
408
417
}
409
418
( Def :: Union ( ..) , _) |
410
419
( Def :: Variant ( ..) , _) |
411
420
( Def :: Ctor ( _, _, CtorKind :: Fictive ) , _) if ns == ValueNS => {
412
- err . span_label ( span , format ! ( "did you mean `{} {{ /* fields */ }}`?" , path_str ) ) ;
421
+ bad_struct_syntax_suggestion ( ) ;
413
422
}
414
423
( Def :: SelfTy ( ..) , _) if ns == ValueNS => {
415
424
err. span_label ( span, fallback_label) ;
0 commit comments