@@ -22,6 +22,7 @@ use rustc_resolve::rustdoc::{
2222 MalformedGenerics , has_primitive_or_keyword_docs, prepare_to_doc_link_resolution,
2323 source_span_for_markdown_range, strip_generics_from_path,
2424} ;
25+ use rustc_session:: config:: CrateType ;
2526use rustc_session:: lint:: Lint ;
2627use rustc_span:: BytePos ;
2728use rustc_span:: hygiene:: MacroKind ;
@@ -1174,7 +1175,6 @@ impl LinkCollector<'_, '_> {
11741175 #[ allow( rustc:: potential_query_instability) ]
11751176 pub ( crate ) fn resolve_ambiguities ( & mut self ) {
11761177 let mut ambiguous_links = mem:: take ( & mut self . ambiguous_links ) ;
1177-
11781178 for ( ( item_id, path_str) , info_items) in ambiguous_links. iter_mut ( ) {
11791179 for info in info_items {
11801180 info. resolved . retain ( |( res, _) | match res {
@@ -2219,17 +2219,6 @@ fn report_malformed_generics(
22192219 ) ;
22202220}
22212221
2222- fn refer_to_single_item ( v : & [ Res ] ) -> bool {
2223- // proc macros can exist in multiple namespaces at once,
2224- // so we need to compare DefIds
2225- v. iter ( )
2226- . try_reduce ( |l, r| match ( l, r) {
2227- ( Res :: Def ( _, lid) , Res :: Def ( _, rid) ) if lid == rid => Some ( l) ,
2228- _ => None ,
2229- } )
2230- . is_some ( )
2231- }
2232-
22332222/// Report an ambiguity error, where there were multiple possible resolutions.
22342223///
22352224/// If all `candidates` have the same kind, it's not possible to disambiguate so in this case,
@@ -2243,16 +2232,48 @@ fn ambiguity_error(
22432232 emit_error : bool ,
22442233) -> bool {
22452234 let mut descrs = FxHashSet :: default ( ) ;
2246- let kinds = candidates
2235+ // proc macros can exist in multiple namespaces at once,
2236+ // so we need to compare DefIds to remove
2237+ // the candidite in the fn namespace
2238+ let mut possible_proc_macro_id = None ;
2239+ let is_proc_macro_crate = cx. tcx . crate_types ( ) == & [ CrateType :: ProcMacro ] ;
2240+ let mut kinds = candidates
22472241 . iter ( )
2248- . map (
2249- |( res, def_id) | {
2250- if let Some ( def_id) = def_id { Res :: from_def_id ( cx. tcx , * def_id) } else { * res }
2251- } ,
2252- )
2253- . filter ( |res| descrs. insert ( res. descr ( ) ) )
2242+ . map ( |( res, def_id) | {
2243+ let r =
2244+ if let Some ( def_id) = def_id { Res :: from_def_id ( cx. tcx , * def_id) } else { * res } ;
2245+ if is_proc_macro_crate && let Res :: Def ( DefKind :: Macro ( _) , id) = r {
2246+ possible_proc_macro_id = Some ( id) ;
2247+ }
2248+ r
2249+ } )
22542250 . collect :: < Vec < _ > > ( ) ;
2255- if descrs. len ( ) == 1 || refer_to_single_item ( & kinds) {
2251+ // in order to properly dedup proc macros,
2252+ // we have to do it in two passes,
2253+ // completing the full traversal to find
2254+ // the possible duplicate in the macro namespace,
2255+ // then another full traversal to eliminate the
2256+ // candidite in the fn namespace.
2257+ // thus, we have to do an iteration after
2258+ // collection is finished.
2259+ //
2260+ // as an optimization, we only deduplicate if we're in a proc-macro crate,
2261+ // and only if we already found something that looks like a proc macro.
2262+ if is_proc_macro_crate && let Some ( macro_id) = possible_proc_macro_id {
2263+ kinds. retain ( |res| {
2264+ if let Res :: Def ( DefKind :: Fn , fn_id) = res
2265+ && macro_id == * fn_id
2266+ {
2267+ false
2268+ } else {
2269+ true
2270+ }
2271+ } ) ;
2272+ }
2273+
2274+ kinds. retain ( |res| descrs. insert ( res. descr ( ) ) ) ;
2275+
2276+ if descrs. len ( ) == 1 {
22562277 // There is no way for users to disambiguate at this point, so better return the first
22572278 // candidate and not show a warning.
22582279 return false ;
0 commit comments