@@ -20,6 +20,7 @@ use rustc_span::symbol::{kw, sym, Ident};
2020use rustc_span:: { BytePos , Span } ;
2121
2222use log:: debug;
23+ use std:: ops:: Deref ;
2324
2425type Res = def:: Res < ast:: NodeId > ;
2526
@@ -147,8 +148,31 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
147148 . map_or ( String :: new ( ) , |res| format ! ( "{} " , res. descr( ) ) ) ;
148149 ( mod_prefix, format ! ( "`{}`" , Segment :: names_to_string( mod_path) ) )
149150 } ;
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+ }
150174 (
151- format ! ( "cannot find {} `{}` in {}{}" , expected , item_str , mod_prefix , mod_str ) ,
175+ message ,
152176 if path_str == "async" && expected. starts_with ( "struct" ) {
153177 "`async` blocks are only allowed in the 2018 edition" . to_string ( )
154178 } else {
@@ -609,6 +633,59 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
609633 }
610634 }
611635 }
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+ }
612689 ( Res :: Def ( DefKind :: Mod , _) , PathSource :: Expr ( Some ( parent) ) ) => {
613690 if !path_sep ( err, & parent) {
614691 return false ;
0 commit comments