@@ -20,6 +20,7 @@ use rustc_span::symbol::{kw, sym, Ident};
20
20
use rustc_span:: { BytePos , Span } ;
21
21
22
22
use log:: debug;
23
+ use std:: ops:: Deref ;
23
24
24
25
type Res = def:: Res < ast:: NodeId > ;
25
26
@@ -147,8 +148,31 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
147
148
. map_or ( String :: new ( ) , |res| format ! ( "{} " , res. descr( ) ) ) ;
148
149
( mod_prefix, format ! ( "`{}`" , Segment :: names_to_string( mod_path) ) )
149
150
} ;
151
+ let message =
152
+ format ! ( "cannot find {} `{}` in {}{}" , expected, item_str, mod_prefix, mod_str) ;
153
+ let colon_span = match self . diagnostic_metadata . current_expr {
154
+ Some ( Expr { kind : ExprKind :: Type ( expr, ty) , .. } ) => {
155
+ Some ( expr. span . between ( ty. span ) )
156
+ }
157
+ _ => None ,
158
+ } ;
159
+ if let Some ( span) = colon_span {
160
+ if self
161
+ . r
162
+ . session
163
+ . parse_sess
164
+ . type_ascription_path_suggestions
165
+ . borrow ( )
166
+ . contains ( & span)
167
+ {
168
+ let mut err = self . r . session . struct_span_err ( item_span, & message) ;
169
+ err. delay_as_bug ( ) ;
170
+ // Already reported this issue on the lhs of the type ascription.
171
+ return ( err, vec ! [ ] ) ;
172
+ }
173
+ }
150
174
(
151
- format ! ( "cannot find {} `{}` in {}{}" , expected , item_str , mod_prefix , mod_str ) ,
175
+ message ,
152
176
if path_str == "async" && expected. starts_with ( "struct" ) {
153
177
"`async` blocks are only allowed in the 2018 edition" . to_string ( )
154
178
} else {
@@ -609,6 +633,59 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
609
633
}
610
634
}
611
635
}
636
+ (
637
+ Res :: Def ( DefKind :: Enum , def_id) ,
638
+ PathSource :: Expr ( Some ( Expr { kind : ExprKind :: Type ( expr, ty) , .. } ) ) ,
639
+ ) => {
640
+ match ( expr. deref ( ) , ty. deref ( ) ) {
641
+ (
642
+ Expr { kind : ExprKind :: Path ( ..) , .. } ,
643
+ Ty { kind : TyKind :: Path ( None , path) , .. } ,
644
+ ) if path. segments . len ( ) == 1 => {
645
+ if let Some ( variants) = self . collect_enum_variants ( def_id) {
646
+ if variants
647
+ . into_iter ( )
648
+ . filter ( |variant| {
649
+ variant. segments [ variant. segments . len ( ) - 1 ] . ident
650
+ == path. segments [ 0 ] . ident
651
+ } )
652
+ . next ( )
653
+ . is_some ( )
654
+ {
655
+ err. delay_as_bug ( ) ;
656
+ let sp = expr. span . between ( ty. span ) ;
657
+ if self
658
+ . r
659
+ . session
660
+ . parse_sess
661
+ . type_ascription_path_suggestions
662
+ . borrow ( )
663
+ . contains ( & sp)
664
+ {
665
+ // We already suggested changing `:` into `::` during parsing.
666
+ return false ;
667
+ }
668
+ self . r
669
+ . session
670
+ . parse_sess
671
+ . type_ascription_path_suggestions
672
+ . borrow_mut ( )
673
+ . insert ( sp) ;
674
+ let mut err =
675
+ self . r . session . struct_span_err ( sp, "expected `::`, found `:`" ) ;
676
+ err. span_suggestion (
677
+ sp,
678
+ "write a path separator instead" ,
679
+ "::" . to_string ( ) ,
680
+ Applicability :: MachineApplicable ,
681
+ ) ;
682
+ err. emit ( ) ;
683
+ }
684
+ }
685
+ }
686
+ _ => { }
687
+ }
688
+ }
612
689
( Res :: Def ( DefKind :: Mod , _) , PathSource :: Expr ( Some ( parent) ) ) => {
613
690
if !path_sep ( err, & parent) {
614
691
return false ;
0 commit comments