@@ -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,8 @@ impl<'a> Resolver<'a> {
278328 _ => false ,
279329 } ;
280330
331+ let ( followed_by_brace, closing_brace) = self . followed_by_brace ( span) ;
332+
281333 match ( def, source) {
282334 ( Def :: Macro ( ..) , _) => {
283335 err. span_suggestion (
@@ -331,52 +383,6 @@ impl<'a> Resolver<'a> {
331383 ) ;
332384 }
333385 } 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- }
380386 match source {
381387 PathSource :: Expr ( Some ( parent) ) => if !path_sep ( err, & parent) {
382388 err. span_label (
@@ -411,7 +417,35 @@ impl<'a> Resolver<'a> {
411417 ( Def :: Union ( ..) , _) |
412418 ( Def :: Variant ( ..) , _) |
413419 ( Def :: Ctor ( _, _, CtorKind :: Fictive ) , _) if ns == ValueNS => {
414- err. span_label ( span, format ! ( "did you mean `{} {{ /* fields */ }}`?" , path_str) ) ;
420+ match source {
421+ PathSource :: Expr ( Some ( parent) ) => if !path_sep ( err, & parent) {
422+ err. span_label (
423+ span,
424+ format ! ( "did you mean `{} {{ /* fields */ }}`?" , path_str) ,
425+ ) ;
426+ }
427+ PathSource :: Expr ( None ) if followed_by_brace == true => {
428+ if let Some ( ( sp, snippet) ) = closing_brace {
429+ err. span_suggestion (
430+ sp,
431+ "surround the struct literal with parenthesis" ,
432+ format ! ( "({})" , snippet) ,
433+ Applicability :: MaybeIncorrect ,
434+ ) ;
435+ } else {
436+ err. span_label (
437+ span,
438+ format ! ( "did you mean `({} {{ /* fields */ }})`?" , path_str) ,
439+ ) ;
440+ }
441+ } ,
442+ _ => {
443+ err. span_label (
444+ span,
445+ format ! ( "did you mean `{} {{ /* fields */ }}`?" , path_str) ,
446+ ) ;
447+ } ,
448+ }
415449 }
416450 ( Def :: SelfTy ( ..) , _) if ns == ValueNS => {
417451 err. span_label ( span, fallback_label) ;
0 commit comments