@@ -17,7 +17,7 @@ use rustc_hir::PrimTy;
1717use rustc_session:: config:: nightly_options;
1818use rustc_span:: hygiene:: MacroKind ;
1919use rustc_span:: symbol:: { kw, sym, Ident } ;
20- use rustc_span:: Span ;
20+ use rustc_span:: { BytePos , Span } ;
2121
2222use log:: debug;
2323
@@ -223,13 +223,31 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
223223 if candidates. is_empty ( ) && is_expected ( Res :: Def ( DefKind :: Enum , crate_def_id) ) {
224224 let enum_candidates =
225225 self . r . lookup_import_candidates ( ident, ns, & self . parent_scope , is_enum_variant) ;
226- let mut enum_candidates = enum_candidates
227- . iter ( )
228- . map ( |suggestion| import_candidate_to_enum_paths ( & suggestion) )
229- . collect :: < Vec < _ > > ( ) ;
230- enum_candidates. sort ( ) ;
231226
232227 if !enum_candidates. is_empty ( ) {
228+ if let ( PathSource :: Type , Some ( span) ) =
229+ ( source, self . diagnostic_metadata . current_type_ascription . last ( ) )
230+ {
231+ if self
232+ . r
233+ . session
234+ . parse_sess
235+ . type_ascription_path_suggestions
236+ . borrow ( )
237+ . contains ( span)
238+ {
239+ // Already reported this issue on the lhs of the type ascription.
240+ err. delay_as_bug ( ) ;
241+ return ( err, candidates) ;
242+ }
243+ }
244+
245+ let mut enum_candidates = enum_candidates
246+ . iter ( )
247+ . map ( |suggestion| import_candidate_to_enum_paths ( & suggestion) )
248+ . collect :: < Vec < _ > > ( ) ;
249+ enum_candidates. sort ( ) ;
250+
233251 // Contextualize for E0412 "cannot find type", but don't belabor the point
234252 // (that it's a variant) for E0573 "expected type, found variant".
235253 let preamble = if res. is_none ( ) {
@@ -484,10 +502,21 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
484502 match source {
485503 PathSource :: Expr ( Some (
486504 parent @ Expr { kind : ExprKind :: Field ( ..) | ExprKind :: MethodCall ( ..) , .. } ,
487- ) ) => {
488- path_sep ( err, & parent) ;
489- }
490- PathSource :: Expr ( None ) if followed_by_brace => {
505+ ) ) if path_sep ( err, & parent) => { }
506+ PathSource :: Expr (
507+ None
508+ | Some ( Expr {
509+ kind :
510+ ExprKind :: Path ( ..)
511+ | ExprKind :: Binary ( ..)
512+ | ExprKind :: Unary ( ..)
513+ | ExprKind :: If ( ..)
514+ | ExprKind :: While ( ..)
515+ | ExprKind :: ForLoop ( ..)
516+ | ExprKind :: Match ( ..) ,
517+ ..
518+ } ) ,
519+ ) if followed_by_brace => {
491520 if let Some ( sp) = closing_brace {
492521 err. multipart_suggestion (
493522 "surround the struct literal with parentheses" ,
@@ -508,11 +537,7 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
508537 ) ;
509538 }
510539 }
511- PathSource :: Expr (
512- None | Some ( Expr { kind : ExprKind :: Call ( ..) | ExprKind :: Path ( ..) , .. } ) ,
513- )
514- | PathSource :: TupleStruct ( _)
515- | PathSource :: Pat => {
540+ PathSource :: Expr ( _) | PathSource :: TupleStruct ( _) | PathSource :: Pat => {
516541 let span = match & source {
517542 PathSource :: Expr ( Some ( Expr {
518543 span, kind : ExprKind :: Call ( _, _) , ..
@@ -593,6 +618,24 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
593618 Res :: Def ( DefKind :: Enum , def_id) ,
594619 PathSource :: TupleStruct ( _) | PathSource :: Expr ( ..) ,
595620 ) => {
621+ if self
622+ . diagnostic_metadata
623+ . current_type_ascription
624+ . last ( )
625+ . map ( |sp| {
626+ self . r
627+ . session
628+ . parse_sess
629+ . type_ascription_path_suggestions
630+ . borrow ( )
631+ . contains ( & sp)
632+ } )
633+ . unwrap_or ( false )
634+ {
635+ err. delay_as_bug ( ) ;
636+ // We already suggested changing `:` into `::` during parsing.
637+ return false ;
638+ }
596639 if let Some ( variants) = self . collect_enum_variants ( def_id) {
597640 if !variants. is_empty ( ) {
598641 let msg = if variants. len ( ) == 1 {
@@ -609,7 +652,7 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
609652 ) ;
610653 }
611654 } else {
612- err. note ( "did you mean to use one of the enum's variants? " ) ;
655+ err. note ( "you might have meant to use one of the enum's variants" ) ;
613656 }
614657 }
615658 ( Res :: Def ( DefKind :: Struct , def_id) , _) if ns == ValueNS => {
@@ -829,77 +872,73 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
829872 fn type_ascription_suggestion ( & self , err : & mut DiagnosticBuilder < ' _ > , base_span : Span ) {
830873 let sm = self . r . session . source_map ( ) ;
831874 let base_snippet = sm. span_to_snippet ( base_span) ;
832- if let Some ( sp) = self . diagnostic_metadata . current_type_ascription . last ( ) {
833- let mut sp = * sp;
834- loop {
835- // Try to find the `:`; bail on first non-':' / non-whitespace.
836- sp = sm. next_point ( sp) ;
837- if let Ok ( snippet) = sm. span_to_snippet ( sp. to ( sm. next_point ( sp) ) ) {
838- let line_sp = sm. lookup_char_pos ( sp. hi ( ) ) . line ;
839- let line_base_sp = sm. lookup_char_pos ( base_span. lo ( ) ) . line ;
840- if snippet == ":" {
841- let mut show_label = true ;
842- if line_sp != line_base_sp {
843- err. span_suggestion_short (
844- sp,
845- "did you mean to use `;` here instead?" ,
846- ";" . to_string ( ) ,
875+ if let Some ( & sp) = self . diagnostic_metadata . current_type_ascription . last ( ) {
876+ if let Ok ( snippet) = sm. span_to_snippet ( sp) {
877+ let len = snippet. trim_end ( ) . len ( ) as u32 ;
878+ if snippet. trim ( ) == ":" {
879+ let colon_sp =
880+ sp. with_lo ( sp. lo ( ) + BytePos ( len - 1 ) ) . with_hi ( sp. lo ( ) + BytePos ( len) ) ;
881+ let mut show_label = true ;
882+ if sm. is_multiline ( sp) {
883+ err. span_suggestion_short (
884+ colon_sp,
885+ "maybe you meant to write `;` here" ,
886+ ";" . to_string ( ) ,
887+ Applicability :: MaybeIncorrect ,
888+ ) ;
889+ } else {
890+ let after_colon_sp =
891+ self . get_colon_suggestion_span ( colon_sp. shrink_to_hi ( ) ) ;
892+ if snippet. len ( ) == 1 {
893+ // `foo:bar`
894+ err. span_suggestion (
895+ colon_sp,
896+ "maybe you meant to write a path separator here" ,
897+ "::" . to_string ( ) ,
847898 Applicability :: MaybeIncorrect ,
848899 ) ;
849- } else {
850- let colon_sp = self . get_colon_suggestion_span ( sp ) ;
851- let after_colon_sp =
852- self . get_colon_suggestion_span ( colon_sp . shrink_to_hi ( ) ) ;
853- if !sm
854- . span_to_snippet ( after_colon_sp )
855- . map ( |s| s == " " )
856- . unwrap_or ( false )
900+ show_label = false ;
901+ if ! self
902+ . r
903+ . session
904+ . parse_sess
905+ . type_ascription_path_suggestions
906+ . borrow_mut ( )
907+ . insert ( colon_sp )
857908 {
858- err. span_suggestion (
859- colon_sp,
860- "maybe you meant to write a path separator here" ,
861- "::" . to_string ( ) ,
862- Applicability :: MaybeIncorrect ,
863- ) ;
864- show_label = false ;
909+ err. delay_as_bug ( ) ;
865910 }
866- if let Ok ( base_snippet) = base_snippet {
867- let mut sp = after_colon_sp;
868- for _ in 0 ..100 {
869- // Try to find an assignment
870- sp = sm. next_point ( sp) ;
871- let snippet = sm. span_to_snippet ( sp. to ( sm. next_point ( sp) ) ) ;
872- match snippet {
873- Ok ( ref x) if x. as_str ( ) == "=" => {
874- err. span_suggestion (
875- base_span,
876- "maybe you meant to write an assignment here" ,
877- format ! ( "let {}" , base_snippet) ,
878- Applicability :: MaybeIncorrect ,
879- ) ;
880- show_label = false ;
881- break ;
882- }
883- Ok ( ref x) if x. as_str ( ) == "\n " => break ,
884- Err ( _) => break ,
885- Ok ( _) => { }
911+ }
912+ if let Ok ( base_snippet) = base_snippet {
913+ let mut sp = after_colon_sp;
914+ for _ in 0 ..100 {
915+ // Try to find an assignment
916+ sp = sm. next_point ( sp) ;
917+ let snippet = sm. span_to_snippet ( sp. to ( sm. next_point ( sp) ) ) ;
918+ match snippet {
919+ Ok ( ref x) if x. as_str ( ) == "=" => {
920+ err. span_suggestion (
921+ base_span,
922+ "maybe you meant to write an assignment here" ,
923+ format ! ( "let {}" , base_snippet) ,
924+ Applicability :: MaybeIncorrect ,
925+ ) ;
926+ show_label = false ;
927+ break ;
886928 }
929+ Ok ( ref x) if x. as_str ( ) == "\n " => break ,
930+ Err ( _) => break ,
931+ Ok ( _) => { }
887932 }
888933 }
889934 }
890- if show_label {
891- err. span_label (
892- base_span,
893- "expecting a type here because of type ascription" ,
894- ) ;
895- }
896- break ;
897- } else if !snippet. trim ( ) . is_empty ( ) {
898- debug ! ( "tried to find type ascription `:` token, couldn't find it" ) ;
899- break ;
900935 }
901- } else {
902- break ;
936+ if show_label {
937+ err. span_label (
938+ base_span,
939+ "expecting a type here because of type ascription" ,
940+ ) ;
941+ }
903942 }
904943 }
905944 }
0 commit comments