@@ -1018,7 +1018,7 @@ impl LinkCollector<'_, '_> {
1018
1018
} else {
1019
1019
// `[char]` when a `char` module is in scope
1020
1020
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 ) ;
1022
1022
return None ;
1023
1023
}
1024
1024
}
@@ -1304,7 +1304,13 @@ impl LinkCollector<'_, '_> {
1304
1304
if ignore_macro {
1305
1305
candidates. macro_ns = None ;
1306
1306
}
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
+ ) ;
1308
1314
None
1309
1315
}
1310
1316
}
@@ -1888,15 +1894,73 @@ fn report_malformed_generics(
1888
1894
) ;
1889
1895
}
1890
1896
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
+
1891
1911
/// Report an ambiguity error, where there were multiple possible resolutions.
1892
1912
fn ambiguity_error (
1893
- cx : & DocContext < ' _ > ,
1913
+ cx : & mut DocContext < ' _ > ,
1894
1914
diag_info : DiagnosticInfo < ' _ > ,
1895
1915
path_str : & str ,
1896
- candidates : Vec < Res > ,
1916
+ mut candidates : Vec < Res > ,
1917
+ module_id : DefId ,
1897
1918
) {
1898
1919
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
+ }
1899
1948
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
+ }
1900
1964
match candidates. as_slice ( ) {
1901
1965
[ first_def, second_def] => {
1902
1966
msg += & format ! (
0 commit comments