@@ -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