@@ -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,8 @@ impl<'a> Resolver<'a> {
276326 _ => false ,
277327 } ;
278328
329+ let ( followed_by_brace, closing_brace) = self . followed_by_brace ( span) ;
330+
279331 match ( def, source) {
280332 ( Def :: Macro ( ..) , _) => {
281333 err. span_suggestion (
@@ -329,52 +381,6 @@ impl<'a> Resolver<'a> {
329381 ) ;
330382 }
331383 } 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- }
378384 match source {
379385 PathSource :: Expr ( Some ( parent) ) => if !path_sep ( err, & parent) {
380386 err. span_label (
@@ -409,7 +415,35 @@ impl<'a> Resolver<'a> {
409415 ( Def :: Union ( ..) , _) |
410416 ( Def :: Variant ( ..) , _) |
411417 ( Def :: Ctor ( _, _, CtorKind :: Fictive ) , _) if ns == ValueNS => {
412- err. span_label ( span, format ! ( "did you mean `{} {{ /* fields */ }}`?" , path_str) ) ;
418+ match source {
419+ PathSource :: Expr ( Some ( parent) ) => if !path_sep ( err, & parent) {
420+ err. span_label (
421+ span,
422+ format ! ( "did you mean `{} {{ /* fields */ }}`?" , path_str) ,
423+ ) ;
424+ }
425+ PathSource :: Expr ( None ) if followed_by_brace == true => {
426+ if let Some ( ( sp, snippet) ) = closing_brace {
427+ err. span_suggestion (
428+ sp,
429+ "surround the struct literal with parenthesis" ,
430+ format ! ( "({})" , snippet) ,
431+ Applicability :: MaybeIncorrect ,
432+ ) ;
433+ } else {
434+ err. span_label (
435+ span,
436+ format ! ( "did you mean `({} {{ /* fields */ }})`?" , path_str) ,
437+ ) ;
438+ }
439+ } ,
440+ _ => {
441+ err. span_label (
442+ span,
443+ format ! ( "did you mean `{} {{ /* fields */ }}`?" , path_str) ,
444+ ) ;
445+ } ,
446+ }
413447 }
414448 ( Def :: SelfTy ( ..) , _) if ns == ValueNS => {
415449 err. span_label ( span, fallback_label) ;
0 commit comments