@@ -238,6 +238,56 @@ impl<'a> Resolver<'a> {
238238 ( err, candidates)
239239 }
240240
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+
241291 /// Provides context-dependent help for errors reported by the `smart_resolve_path_fragment`
242292 /// function.
243293 /// Returns `true` if able to provide context-dependent help.
@@ -276,6 +326,39 @@ impl<'a> Resolver<'a> {
276326 _ => false ,
277327 } ;
278328
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+
279362 match ( def, source) {
280363 ( Def :: Macro ( ..) , _) => {
281364 err. span_suggestion (
@@ -329,87 +412,13 @@ impl<'a> Resolver<'a> {
329412 ) ;
330413 }
331414 } 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 ( ) ;
407416 }
408417 }
409418 ( Def :: Union ( ..) , _) |
410419 ( Def :: Variant ( ..) , _) |
411420 ( Def :: Ctor ( _, _, CtorKind :: Fictive ) , _) if ns == ValueNS => {
412- err . span_label ( span , format ! ( "did you mean `{} {{ /* fields */ }}`?" , path_str ) ) ;
421+ bad_struct_syntax_suggestion ( ) ;
413422 }
414423 ( Def :: SelfTy ( ..) , _) if ns == ValueNS => {
415424 err. span_label ( span, fallback_label) ;
0 commit comments