@@ -17,7 +17,7 @@ use rustc_hir::PrimTy;
17
17
use rustc_session:: config:: nightly_options;
18
18
use rustc_span:: hygiene:: MacroKind ;
19
19
use rustc_span:: symbol:: { kw, sym, Ident } ;
20
- use rustc_span:: Span ;
20
+ use rustc_span:: { BytePos , Span } ;
21
21
22
22
use log:: debug;
23
23
use std:: ops:: Deref ;
@@ -226,16 +226,16 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
226
226
self . r . lookup_import_candidates ( ident, ns, & self . parent_scope , is_enum_variant) ;
227
227
228
228
if !enum_candidates. is_empty ( ) {
229
- if let ( PathSource :: Type , Some ( Expr { kind : ExprKind :: Type ( expr , ty ) , .. } ) ) =
230
- ( source, self . diagnostic_metadata . current_expr )
229
+ if let ( PathSource :: Type , Some ( span ) ) =
230
+ ( source, self . diagnostic_metadata . current_type_ascription . last ( ) )
231
231
{
232
232
if self
233
233
. r
234
234
. session
235
235
. parse_sess
236
236
. type_ascription_path_suggestions
237
237
. borrow ( )
238
- . contains ( & expr . span . between ( ty . span ) )
238
+ . contains ( span)
239
239
{
240
240
// Already reported this issue on the lhs of the type ascription.
241
241
err. delay_as_bug ( ) ;
@@ -666,6 +666,24 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
666
666
Res :: Def ( DefKind :: Enum , def_id) ,
667
667
PathSource :: TupleStruct ( _) | PathSource :: Expr ( ..) ,
668
668
) => {
669
+ if self
670
+ . diagnostic_metadata
671
+ . current_type_ascription
672
+ . last ( )
673
+ . map ( |sp| {
674
+ self . r
675
+ . session
676
+ . parse_sess
677
+ . type_ascription_path_suggestions
678
+ . borrow ( )
679
+ . contains ( & sp)
680
+ } )
681
+ . unwrap_or ( false )
682
+ {
683
+ err. delay_as_bug ( ) ;
684
+ // We already suggested changing `:` into `::` during parsing.
685
+ return false ;
686
+ }
669
687
if let Some ( variants) = self . collect_enum_variants ( def_id) {
670
688
if !variants. is_empty ( ) {
671
689
let msg = if variants. len ( ) == 1 {
@@ -903,93 +921,79 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
903
921
fn type_ascription_suggestion ( & self , err : & mut DiagnosticBuilder < ' _ > , base_span : Span ) {
904
922
let sm = self . r . session . source_map ( ) ;
905
923
let base_snippet = sm. span_to_snippet ( base_span) ;
906
- if let Some ( sp) = self . diagnostic_metadata . current_type_ascription . last ( ) {
907
- let mut sp = * sp;
908
- loop {
909
- // Try to find the `:`; bail on first non-':' / non-whitespace.
910
- sp = sm. next_point ( sp) ;
911
- if let Ok ( snippet) = sm. span_to_snippet ( sp. to ( sm. next_point ( sp) ) ) {
912
- let line_sp = sm. lookup_char_pos ( sp. hi ( ) ) . line ;
913
- let line_base_sp = sm. lookup_char_pos ( base_span. lo ( ) ) . line ;
914
- if snippet == ":" {
915
- let mut show_label = true ;
916
- if line_sp != line_base_sp {
917
- err. span_suggestion_short (
918
- sp,
919
- "did you mean to use `;` here instead?" ,
920
- ";" . to_string ( ) ,
924
+ if let Some ( & sp) = self . diagnostic_metadata . current_type_ascription . last ( ) {
925
+ if let Ok ( snippet) = sm. span_to_snippet ( sp) {
926
+ let len = snippet. trim_end ( ) . len ( ) as u32 ;
927
+ if snippet. trim ( ) == ":" {
928
+ let colon_sp =
929
+ sp. with_lo ( sp. lo ( ) + BytePos ( len - 1 ) ) . with_hi ( sp. lo ( ) + BytePos ( len) ) ;
930
+ let mut show_label = true ;
931
+ if sm. is_multiline ( sp) {
932
+ err. span_suggestion_short (
933
+ colon_sp,
934
+ "maybe you meant to write `;` here" ,
935
+ ";" . to_string ( ) ,
936
+ Applicability :: MaybeIncorrect ,
937
+ ) ;
938
+ } else {
939
+ let after_colon_sp =
940
+ self . get_colon_suggestion_span ( colon_sp. shrink_to_hi ( ) ) ;
941
+ if snippet. len ( ) == 1 {
942
+ // `foo:bar`
943
+ err. span_suggestion (
944
+ colon_sp,
945
+ "maybe you meant to write a path separator here" ,
946
+ "::" . to_string ( ) ,
921
947
Applicability :: MaybeIncorrect ,
922
948
) ;
923
- } else {
924
- let colon_sp = self . get_colon_suggestion_span ( sp ) ;
925
- let after_colon_sp =
926
- self . get_colon_suggestion_span ( colon_sp . shrink_to_hi ( ) ) ;
927
- if !sm
928
- . span_to_snippet ( after_colon_sp )
929
- . map ( |s| s == " " )
930
- . unwrap_or ( false )
949
+ show_label = false ;
950
+ if self
951
+ . r
952
+ . session
953
+ . parse_sess
954
+ . type_ascription_path_suggestions
955
+ . borrow ( )
956
+ . contains ( & colon_sp )
931
957
{
932
- err. span_suggestion (
933
- colon_sp,
934
- "maybe you meant to write a path separator here" ,
935
- "::" . to_string ( ) ,
936
- Applicability :: MaybeIncorrect ,
937
- ) ;
938
- show_label = false ;
939
- if self
940
- . r
941
- . session
942
- . parse_sess
943
- . type_ascription_path_suggestions
944
- . borrow ( )
945
- . contains ( & colon_sp)
946
- {
947
- err. delay_as_bug ( ) ;
948
- }
949
- self . r
950
- . session
951
- . parse_sess
952
- . type_ascription_path_suggestions
953
- . borrow_mut ( )
954
- . insert ( colon_sp) ;
958
+ err. delay_as_bug ( ) ;
955
959
}
956
- if let Ok ( base_snippet) = base_snippet {
957
- let mut sp = after_colon_sp;
958
- for _ in 0 ..100 {
959
- // Try to find an assignment
960
- sp = sm. next_point ( sp) ;
961
- let snippet = sm. span_to_snippet ( sp. to ( sm. next_point ( sp) ) ) ;
962
- match snippet {
963
- Ok ( ref x) if x. as_str ( ) == "=" => {
964
- err. span_suggestion (
965
- base_span,
966
- "maybe you meant to write an assignment here" ,
967
- format ! ( "let {}" , base_snippet) ,
968
- Applicability :: MaybeIncorrect ,
969
- ) ;
970
- show_label = false ;
971
- break ;
972
- }
973
- Ok ( ref x) if x. as_str ( ) == "\n " => break ,
974
- Err ( _) => break ,
975
- Ok ( _) => { }
960
+ self . r
961
+ . session
962
+ . parse_sess
963
+ . type_ascription_path_suggestions
964
+ . borrow_mut ( )
965
+ . insert ( colon_sp) ;
966
+ }
967
+ if let Ok ( base_snippet) = base_snippet {
968
+ let mut sp = after_colon_sp;
969
+ for _ in 0 ..100 {
970
+ // Try to find an assignment
971
+ sp = sm. next_point ( sp) ;
972
+ let snippet = sm. span_to_snippet ( sp. to ( sm. next_point ( sp) ) ) ;
973
+ match snippet {
974
+ Ok ( ref x) if x. as_str ( ) == "=" => {
975
+ err. span_suggestion (
976
+ base_span,
977
+ "maybe you meant to write an assignment here" ,
978
+ format ! ( "let {}" , base_snippet) ,
979
+ Applicability :: MaybeIncorrect ,
980
+ ) ;
981
+ show_label = false ;
982
+ break ;
976
983
}
984
+ Ok ( ref x) if x. as_str ( ) == "\n " => break ,
985
+ Err ( _) => break ,
986
+ Ok ( _) => { }
977
987
}
978
988
}
979
989
}
980
- if show_label {
981
- err. span_label (
982
- base_span,
983
- "expecting a type here because of type ascription" ,
984
- ) ;
985
- }
986
- break ;
987
- } else if !snippet. trim ( ) . is_empty ( ) {
988
- debug ! ( "tried to find type ascription `:` token, couldn't find it" ) ;
989
- break ;
990
990
}
991
- } else {
992
- break ;
991
+ if show_label {
992
+ err. span_label (
993
+ base_span,
994
+ "expecting a type here because of type ascription" ,
995
+ ) ;
996
+ }
993
997
}
994
998
}
995
999
}
0 commit comments