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