@@ -1018,7 +1018,7 @@ impl LinkCollector<'_, '_> {
10181018 } else {
10191019 // `[char]` when a `char` module is in scope
10201020 let candidates = vec ! [ res, prim] ;
1021- ambiguity_error ( self . cx , diag_info, path_str, candidates) ;
1021+ ambiguity_error ( self . cx , diag_info, path_str, candidates, module_id ) ;
10221022 return None ;
10231023 }
10241024 }
@@ -1304,7 +1304,13 @@ impl LinkCollector<'_, '_> {
13041304 if ignore_macro {
13051305 candidates. macro_ns = None ;
13061306 }
1307- ambiguity_error ( self . cx , diag, path_str, candidates. present_items ( ) . collect ( ) ) ;
1307+ ambiguity_error (
1308+ self . cx ,
1309+ diag,
1310+ path_str,
1311+ candidates. present_items ( ) . collect ( ) ,
1312+ base_node,
1313+ ) ;
13081314 None
13091315 }
13101316 }
@@ -1888,15 +1894,73 @@ fn report_malformed_generics(
18881894 ) ;
18891895}
18901896
1897+ fn get_matching_items (
1898+ cx : & DocContext < ' _ > ,
1899+ item_name : & str ,
1900+ candidates : & mut Vec < Res > ,
1901+ def_id : DefId ,
1902+ ) {
1903+ let assoc_items = cx. tcx . associated_items ( def_id) ;
1904+ for assoc_item in assoc_items. in_definition_order ( ) {
1905+ if assoc_item. name . as_str ( ) == item_name {
1906+ candidates. push ( Res :: Def ( assoc_item. kind . as_def_kind ( ) , assoc_item. def_id ) ) ;
1907+ }
1908+ }
1909+ }
1910+
18911911/// Report an ambiguity error, where there were multiple possible resolutions.
18921912fn ambiguity_error (
1893- cx : & DocContext < ' _ > ,
1913+ cx : & mut DocContext < ' _ > ,
18941914 diag_info : DiagnosticInfo < ' _ > ,
18951915 path_str : & str ,
1896- candidates : Vec < Res > ,
1916+ mut candidates : Vec < Res > ,
1917+ module_id : DefId ,
18971918) {
18981919 let mut msg = format ! ( "`{}` is " , path_str) ;
1920+ let mut def_id_counts = FxHashMap :: default ( ) ;
1921+ let mut need_dedup = false ;
1922+
1923+ // If the item is an impl block or a trait, we need to disambiguate even further, otherwise
1924+ // `Res` will always tell it's an impl/trait.
1925+ for candidate in & candidates {
1926+ if let Some ( def_id) = candidate. def_id ( cx. tcx ) {
1927+ def_id_counts
1928+ . entry ( def_id)
1929+ . and_modify ( |( count, _) | {
1930+ * count += 1 ;
1931+ need_dedup = true ;
1932+ } )
1933+ . or_insert ( ( 1 , * candidate) ) ;
1934+ }
1935+ }
1936+ if need_dedup && let Some ( item_name) = path_str. split ( "::" ) . last ( ) {
1937+ candidates. clear ( ) ;
1938+ for ( def_id, ( count, candidate) ) in def_id_counts. into_iter ( ) {
1939+ if count > 1 {
1940+ if matches ! ( cx. tcx. def_kind( def_id) , DefKind :: Trait | DefKind :: Impl { .. } ) {
1941+ // If it's a trait or an impl block, we can directly get the items from it.
1942+ get_matching_items ( cx, item_name, & mut candidates, def_id) ;
1943+ } else {
1944+ // We go through the type's impl blocks.
1945+ for impl_ in cx. tcx . inherent_impls ( def_id) {
1946+ get_matching_items ( cx, item_name, & mut candidates, * impl_) ;
1947+ }
18991948
1949+ // We now go through trait impls.
1950+ let trait_impls = trait_impls_for (
1951+ cx,
1952+ cx. tcx . type_of ( def_id) . subst_identity ( ) ,
1953+ module_id,
1954+ ) ;
1955+ for ( impl_, _) in trait_impls {
1956+ get_matching_items ( cx, item_name, & mut candidates, impl_) ;
1957+ }
1958+ }
1959+ } else {
1960+ candidates. push ( candidate) ;
1961+ }
1962+ }
1963+ }
19001964 match candidates. as_slice ( ) {
19011965 [ first_def, second_def] => {
19021966 msg += & format ! (
0 commit comments