@@ -240,6 +240,56 @@ impl<'a> Resolver<'a> {
240240 ( err, candidates)
241241 }
242242
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+
243293 /// Provides context-dependent help for errors reported by the `smart_resolve_path_fragment`
244294 /// function.
245295 /// Returns `true` if able to provide context-dependent help.
@@ -278,6 +328,39 @@ impl<'a> Resolver<'a> {
278328 _ => false ,
279329 } ;
280330
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+
281364 match ( def, source) {
282365 ( Def :: Macro ( ..) , _) => {
283366 err. span_suggestion (
@@ -331,87 +414,13 @@ impl<'a> Resolver<'a> {
331414 ) ;
332415 }
333416 } 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 ( ) ;
409418 }
410419 }
411420 ( Def :: Union ( ..) , _) |
412421 ( Def :: Variant ( ..) , _) |
413422 ( Def :: Ctor ( _, _, CtorKind :: Fictive ) , _) if ns == ValueNS => {
414- err . span_label ( span , format ! ( "did you mean `{} {{ /* fields */ }}`?" , path_str ) ) ;
423+ bad_struct_syntax_suggestion ( ) ;
415424 }
416425 ( Def :: SelfTy ( ..) , _) if ns == ValueNS => {
417426 err. span_label ( span, fallback_label) ;
0 commit comments