@@ -2191,11 +2191,9 @@ impl<'a> Resolver<'a> {
2191
2191
}
2192
2192
2193
2193
// Try Levenshtein if nothing else worked.
2194
- if path. len ( ) == 1 {
2195
- if let Some ( candidate) = this. lookup_typo_candidate ( name, ns, is_expected) {
2196
- err. span_label ( span, & format ! ( "did you mean `{}`?" , candidate) ) ;
2197
- return err;
2198
- }
2194
+ if let Some ( candidate) = this. lookup_typo_candidate ( path, ns, is_expected) {
2195
+ err. span_label ( span, & format ! ( "did you mean `{}`?" , candidate) ) ;
2196
+ return err;
2199
2197
}
2200
2198
2201
2199
// Fallback label.
@@ -2649,21 +2647,72 @@ impl<'a> Resolver<'a> {
2649
2647
}
2650
2648
2651
2649
fn lookup_typo_candidate < FilterFn > ( & mut self ,
2652
- name : Name ,
2650
+ path : & [ Ident ] ,
2653
2651
ns : Namespace ,
2654
2652
filter_fn : FilterFn )
2655
- -> Option < Name >
2653
+ -> Option < String >
2656
2654
where FilterFn : Fn ( Def ) -> bool
2657
2655
{
2658
- // FIXME: bindings in ribs provide quite modest set of candidates,
2659
- // extend it with other names in scope.
2660
- let names = self . ribs [ ns] . iter ( ) . rev ( ) . flat_map ( |rib| {
2661
- rib. bindings . iter ( ) . filter_map ( |( ident, def) | {
2662
- if filter_fn ( * def) { Some ( & ident. name ) } else { None }
2663
- } )
2664
- } ) ;
2665
- match find_best_match_for_name ( names, & name. as_str ( ) , None ) {
2666
- Some ( found) if found != name => Some ( found) ,
2656
+ let add_module_candidates = |module : Module , names : & mut Vec < Name > | {
2657
+ for ( & ( ident, _) , resolution) in module. resolutions . borrow ( ) . iter ( ) {
2658
+ if let Some ( binding) = resolution. borrow ( ) . binding {
2659
+ if filter_fn ( binding. def ( ) ) {
2660
+ names. push ( ident. name ) ;
2661
+ }
2662
+ }
2663
+ }
2664
+ } ;
2665
+
2666
+ let mut names = Vec :: new ( ) ;
2667
+ let prefix_str = if path. len ( ) == 1 {
2668
+ // Search in lexical scope.
2669
+ // Walk backwards up the ribs in scope and collect candidates.
2670
+ for rib in self . ribs [ ns] . iter ( ) . rev ( ) {
2671
+ // Locals and type parameters
2672
+ for ( ident, def) in & rib. bindings {
2673
+ if filter_fn ( * def) {
2674
+ names. push ( ident. name ) ;
2675
+ }
2676
+ }
2677
+ // Items in scope
2678
+ if let ModuleRibKind ( module) = rib. kind {
2679
+ // Items from this module
2680
+ add_module_candidates ( module, & mut names) ;
2681
+
2682
+ if let ModuleKind :: Block ( ..) = module. kind {
2683
+ // We can see through blocks
2684
+ } else {
2685
+ // Items from the prelude
2686
+ if let Some ( prelude) = self . prelude {
2687
+ if !module. no_implicit_prelude {
2688
+ add_module_candidates ( prelude, & mut names) ;
2689
+ }
2690
+ }
2691
+ break ;
2692
+ }
2693
+ }
2694
+ }
2695
+ // Add primitive types to the mix
2696
+ if filter_fn ( Def :: PrimTy ( TyBool ) ) {
2697
+ for ( name, _) in & self . primitive_type_table . primitive_types {
2698
+ names. push ( * name) ;
2699
+ }
2700
+ }
2701
+ String :: new ( )
2702
+ } else {
2703
+ // Search in module.
2704
+ let mod_path = & path[ ..path. len ( ) - 1 ] ;
2705
+ if let PathResult :: Module ( module) = self . resolve_path ( mod_path, Some ( TypeNS ) , None ) {
2706
+ add_module_candidates ( module, & mut names) ;
2707
+ }
2708
+ names_to_string ( mod_path) + "::"
2709
+ } ;
2710
+
2711
+ let name = path[ path. len ( ) - 1 ] . name ;
2712
+ // Make sure error reporting is deterministic.
2713
+ names. sort_by_key ( |name| name. as_str ( ) ) ;
2714
+ match find_best_match_for_name ( names. iter ( ) , & name. as_str ( ) , None ) {
2715
+ Some ( found) if found != name => Some ( format ! ( "{}{}" , prefix_str, found) ) ,
2667
2716
_ => None ,
2668
2717
}
2669
2718
}
0 commit comments