@@ -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
@@ -2495,6 +2504,7 @@ impl<'a> Resolver<'a> {
2495
2504
// Fallback label.
2496
2505
if !levenshtein_worked {
2497
2506
err. span_label ( base_span, fallback_label) ;
2507
+ this. type_ascription_suggestion ( & mut err, base_span) ;
2498
2508
}
2499
2509
err
2500
2510
} ;
@@ -2550,6 +2560,41 @@ impl<'a> Resolver<'a> {
2550
2560
resolution
2551
2561
}
2552
2562
2563
+ fn type_ascription_suggestion ( & self ,
2564
+ err : & mut DiagnosticBuilder ,
2565
+ base_span : Span ) {
2566
+ debug ! ( "type_ascription_suggetion {:?}" , base_span) ;
2567
+ let cm = self . session . codemap ( ) ;
2568
+ debug ! ( "self.current_type_ascription {:?}" , self . current_type_ascription) ;
2569
+ if let Some ( sp) = self . current_type_ascription . last ( ) {
2570
+ let mut sp = * sp;
2571
+ loop { // try to find the `:`, bail on first non-':'/non-whitespace
2572
+ sp = sp. next_point ( ) ;
2573
+ if let Ok ( snippet) = cm. span_to_snippet ( sp. to ( sp. next_point ( ) ) ) {
2574
+ debug ! ( "snippet {:?}" , snippet) ;
2575
+ let line_sp = cm. lookup_char_pos ( sp. hi ) . line ;
2576
+ let line_base_sp = cm. lookup_char_pos ( base_span. lo ) . line ;
2577
+ debug ! ( "{:?} {:?}" , line_sp, line_base_sp) ;
2578
+ if snippet == ":" {
2579
+ err. span_label ( base_span,
2580
+ "expecting a type here because of type ascription" ) ;
2581
+ if line_sp != line_base_sp {
2582
+ err. span_suggestion_short ( sp,
2583
+ "did you mean to use `;` here instead?" ,
2584
+ ";" . to_string ( ) ) ;
2585
+ }
2586
+ break ;
2587
+ } else if snippet. trim ( ) . len ( ) != 0 {
2588
+ debug ! ( "tried to find type ascription `:` token, couldn't find it" ) ;
2589
+ break ;
2590
+ }
2591
+ } else {
2592
+ break ;
2593
+ }
2594
+ }
2595
+ }
2596
+ }
2597
+
2553
2598
fn self_type_is_available ( & mut self , span : Span ) -> bool {
2554
2599
let binding = self . resolve_ident_in_lexical_scope ( keywords:: SelfType . ident ( ) ,
2555
2600
TypeNS , false , span) ;
@@ -3166,7 +3211,11 @@ impl<'a> Resolver<'a> {
3166
3211
self . resolve_expr ( argument, None ) ;
3167
3212
}
3168
3213
}
3169
-
3214
+ ExprKind :: Type ( ref type_expr, _) => {
3215
+ self . current_type_ascription . push ( type_expr. span ) ;
3216
+ visit:: walk_expr ( self , expr) ;
3217
+ self . current_type_ascription . pop ( ) ;
3218
+ }
3170
3219
_ => {
3171
3220
visit:: walk_expr ( self , expr) ;
3172
3221
}
0 commit comments