@@ -461,7 +461,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
461461                    static_candidates :  Vec :: new ( ) , 
462462                    unsatisfied_predicates :  Vec :: new ( ) , 
463463                    out_of_scope_traits :  Vec :: new ( ) , 
464-                     lev_candidate :  None , 
464+                     similar_candidate :  None , 
465465                    mode, 
466466                } ) ) ; 
467467            } 
@@ -1076,13 +1076,13 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
10761076        if  let  Some ( ( kind,  def_id) )  = private_candidate { 
10771077            return  Err ( MethodError :: PrivateMatch ( kind,  def_id,  out_of_scope_traits) ) ; 
10781078        } 
1079-         let  lev_candidate  = self . probe_for_lev_candidate ( ) ?; 
1079+         let  similar_candidate  = self . probe_for_similar_candidate ( ) ?; 
10801080
10811081        Err ( MethodError :: NoMatch ( NoMatchData  { 
10821082            static_candidates, 
10831083            unsatisfied_predicates, 
10841084            out_of_scope_traits, 
1085-             lev_candidate , 
1085+             similar_candidate , 
10861086            mode :  self . mode , 
10871087        } ) ) 
10881088    } 
@@ -1787,7 +1787,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
17871787    /// Similarly to `probe_for_return_type`, this method attempts to find the best matching 
17881788/// candidate method where the method name may have been misspelled. Similarly to other 
17891789/// Levenshtein based suggestions, we provide at most one such suggestion. 
1790- fn  probe_for_lev_candidate ( & mut  self )  -> Result < Option < ty:: AssocItem > ,  MethodError < ' tcx > >  { 
1790+ fn  probe_for_similar_candidate ( & mut  self )  -> Result < Option < ty:: AssocItem > ,  MethodError < ' tcx > >  { 
17911791        debug ! ( "probing for method names similar to {:?}" ,  self . method_name) ; 
17921792
17931793        let  steps = self . steps . clone ( ) ; 
@@ -1831,6 +1831,12 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
18311831                        None , 
18321832                    ) 
18331833                } 
1834+                 . or_else ( || { 
1835+                     applicable_close_candidates
1836+                         . iter ( ) 
1837+                         . find ( |cand| self . matches_by_doc_alias ( cand. def_id ) ) 
1838+                         . map ( |cand| cand. name ) 
1839+                 } ) 
18341840                . unwrap ( ) ; 
18351841                Ok ( applicable_close_candidates. into_iter ( ) . find ( |method| method. name  == best_name) ) 
18361842            } 
@@ -1981,6 +1987,38 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
19811987        } 
19821988    } 
19831989
1990+     /// Determine if the associated item withe the given DefId matches 
1991+ /// the desired name via a doc alias. 
1992+ fn  matches_by_doc_alias ( & self ,  def_id :  DefId )  -> bool  { 
1993+         let  Some ( name)  = self . method_name  else  {  return  false ;  } ; 
1994+         let  Some ( local_def_id)  = def_id. as_local ( )  else  {  return  false ;  } ; 
1995+         let  hir_id = self . fcx . tcx . hir ( ) . local_def_id_to_hir_id ( local_def_id) ; 
1996+         let  attrs = self . fcx . tcx . hir ( ) . attrs ( hir_id) ; 
1997+         for  attr in  attrs { 
1998+             let  sym:: doc = attr. name_or_empty ( )  else  {  continue ;  } ; 
1999+             let  Some ( values)  = attr. meta_item_list ( )  else  {  continue ;  } ; 
2000+             for  v in  values { 
2001+                 if  v. name_or_empty ( )  != sym:: alias { 
2002+                     continue ; 
2003+                 } 
2004+                 if  let  Some ( nested)  = v. meta_item_list ( )  { 
2005+                     // #[doc(alias("foo", "bar"))] 
2006+                     for  n in  nested { 
2007+                         if  let  Some ( lit)  = n. lit ( )  && name. as_str ( )  == lit. symbol . as_str ( )  { 
2008+                             return  true ; 
2009+                         } 
2010+                     } 
2011+                 }  else  if  let  Some ( meta)  = v. meta_item ( ) 
2012+                     && let  Some ( lit)  = meta. name_value_literal ( ) 
2013+                     && name. as_str ( )  == lit. symbol . as_str ( )  { 
2014+                         // #[doc(alias = "foo")] 
2015+                         return  true ; 
2016+                 } 
2017+             } 
2018+         } 
2019+         false 
2020+     } 
2021+ 
19842022    /// Finds the method with the appropriate name (or return type, as the case may be). If 
19852023/// `allow_similar_names` is set, find methods with close-matching names. 
19862024// The length of the returned iterator is nearly always 0 or 1 and this 
@@ -1996,6 +2034,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
19962034                        if  !self . is_relevant_kind_for_mode ( x. kind )  { 
19972035                            return  false ; 
19982036                        } 
2037+                         if  self . matches_by_doc_alias ( x. def_id )  { 
2038+                             return  true ; 
2039+                         } 
19992040                        match  lev_distance_with_substrings ( name. as_str ( ) ,  x. name . as_str ( ) ,  max_dist) 
20002041                        { 
20012042                            Some ( d)  => d > 0 , 
0 commit comments