@@ -599,19 +599,24 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
599
599
self . resolve_local ( local) ;
600
600
}
601
601
fn visit_ty ( & mut self , ty : & ' tcx Ty ) {
602
- if let TyKind :: Path ( ref qself, ref path) = ty. node {
603
- self . smart_resolve_path ( ty. id , qself. as_ref ( ) , path, PathSource :: Type ) ;
604
- } else if let TyKind :: ImplicitSelf = ty. node {
605
- let self_ty = keywords:: SelfType . ident ( ) ;
606
- let def = self . resolve_ident_in_lexical_scope ( self_ty, TypeNS , true , ty. span )
607
- . map_or ( Def :: Err , |d| d. def ( ) ) ;
608
- self . record_def ( ty. id , PathResolution :: new ( def) ) ;
609
- } else if let TyKind :: Array ( ref element, ref length) = ty. node {
610
- self . visit_ty ( element) ;
611
- self . with_constant_rib ( |this| {
612
- this. visit_expr ( length) ;
613
- } ) ;
614
- return ;
602
+ match ty. node {
603
+ TyKind :: Path ( ref qself, ref path) => {
604
+ self . smart_resolve_path ( ty. id , qself. as_ref ( ) , path, PathSource :: Type ) ;
605
+ }
606
+ TyKind :: ImplicitSelf => {
607
+ let self_ty = keywords:: SelfType . ident ( ) ;
608
+ let def = self . resolve_ident_in_lexical_scope ( self_ty, TypeNS , true , ty. span )
609
+ . map_or ( Def :: Err , |d| d. def ( ) ) ;
610
+ self . record_def ( ty. id , PathResolution :: new ( def) ) ;
611
+ }
612
+ TyKind :: Array ( ref element, ref length) => {
613
+ self . visit_ty ( element) ;
614
+ self . with_constant_rib ( |this| {
615
+ this. visit_expr ( length) ;
616
+ } ) ;
617
+ return ;
618
+ }
619
+ _ => ( ) ,
615
620
}
616
621
visit:: walk_ty ( self , ty) ;
617
622
}
@@ -1221,6 +1226,9 @@ pub struct Resolver<'a> {
1221
1226
// This table maps struct IDs into struct constructor IDs,
1222
1227
// it's not used during normal resolution, only for better error reporting.
1223
1228
struct_constructors : DefIdMap < ( Def , ty:: Visibility ) > ,
1229
+
1230
+ // Only used for better errors on `fn(): fn()`
1231
+ current_type_ascription : Vec < Span > ,
1224
1232
}
1225
1233
1226
1234
pub struct ResolverArenas < ' a > {
@@ -1411,6 +1419,7 @@ impl<'a> Resolver<'a> {
1411
1419
struct_constructors : DefIdMap ( ) ,
1412
1420
found_unresolved_macro : false ,
1413
1421
unused_macros : FxHashSet ( ) ,
1422
+ current_type_ascription : Vec :: new ( ) ,
1414
1423
}
1415
1424
}
1416
1425
@@ -2499,6 +2508,7 @@ impl<'a> Resolver<'a> {
2499
2508
// Fallback label.
2500
2509
if !levenshtein_worked {
2501
2510
err. span_label ( base_span, fallback_label) ;
2511
+ this. type_ascription_suggestion ( & mut err, base_span) ;
2502
2512
}
2503
2513
err
2504
2514
} ;
@@ -2554,6 +2564,41 @@ impl<'a> Resolver<'a> {
2554
2564
resolution
2555
2565
}
2556
2566
2567
+ fn type_ascription_suggestion ( & self ,
2568
+ err : & mut DiagnosticBuilder ,
2569
+ base_span : Span ) {
2570
+ debug ! ( "type_ascription_suggetion {:?}" , base_span) ;
2571
+ let cm = self . session . codemap ( ) ;
2572
+ debug ! ( "self.current_type_ascription {:?}" , self . current_type_ascription) ;
2573
+ if let Some ( sp) = self . current_type_ascription . last ( ) {
2574
+ let mut sp = * sp;
2575
+ loop { // try to find the `:`, bail on first non-':'/non-whitespace
2576
+ sp = sp. next_point ( ) ;
2577
+ if let Ok ( snippet) = cm. span_to_snippet ( sp. to ( sp. next_point ( ) ) ) {
2578
+ debug ! ( "snippet {:?}" , snippet) ;
2579
+ let line_sp = cm. lookup_char_pos ( sp. hi ) . line ;
2580
+ let line_base_sp = cm. lookup_char_pos ( base_span. lo ) . line ;
2581
+ debug ! ( "{:?} {:?}" , line_sp, line_base_sp) ;
2582
+ if snippet == ":" {
2583
+ err. span_label ( base_span,
2584
+ "expecting a type here because of type ascription" ) ;
2585
+ if line_sp != line_base_sp {
2586
+ err. span_suggestion_short ( sp,
2587
+ "did you mean to use `;` here instead?" ,
2588
+ ";" . to_string ( ) ) ;
2589
+ }
2590
+ break ;
2591
+ } else if snippet. trim ( ) . len ( ) != 0 {
2592
+ debug ! ( "tried to find type ascription `:` token, couldn't find it" ) ;
2593
+ break ;
2594
+ }
2595
+ } else {
2596
+ break ;
2597
+ }
2598
+ }
2599
+ }
2600
+ }
2601
+
2557
2602
fn self_type_is_available ( & mut self , span : Span ) -> bool {
2558
2603
let binding = self . resolve_ident_in_lexical_scope ( keywords:: SelfType . ident ( ) ,
2559
2604
TypeNS , false , span) ;
@@ -3170,7 +3215,11 @@ impl<'a> Resolver<'a> {
3170
3215
self . resolve_expr ( argument, None ) ;
3171
3216
}
3172
3217
}
3173
-
3218
+ ExprKind :: Type ( ref type_expr, _) => {
3219
+ self . current_type_ascription . push ( type_expr. span ) ;
3220
+ visit:: walk_expr ( self , expr) ;
3221
+ self . current_type_ascription . pop ( ) ;
3222
+ }
3174
3223
_ => {
3175
3224
visit:: walk_expr ( self , expr) ;
3176
3225
}
0 commit comments