@@ -22,7 +22,7 @@ use rustc_resolve::rustdoc::{
22
22
MalformedGenerics , has_primitive_or_keyword_docs, prepare_to_doc_link_resolution,
23
23
source_span_for_markdown_range, strip_generics_from_path,
24
24
} ;
25
- use rustc_session:: lint:: Lint ;
25
+ use rustc_session:: { lint:: Lint , config :: CrateType } ;
26
26
use rustc_span:: BytePos ;
27
27
use rustc_span:: hygiene:: MacroKind ;
28
28
use rustc_span:: symbol:: { Ident , Symbol , sym} ;
@@ -1174,7 +1174,6 @@ impl LinkCollector<'_, '_> {
1174
1174
#[ allow( rustc:: potential_query_instability) ]
1175
1175
pub ( crate ) fn resolve_ambiguities ( & mut self ) {
1176
1176
let mut ambiguous_links = mem:: take ( & mut self . ambiguous_links ) ;
1177
-
1178
1177
for ( ( item_id, path_str) , info_items) in ambiguous_links. iter_mut ( ) {
1179
1178
for info in info_items {
1180
1179
info. resolved . retain ( |( res, _) | match res {
@@ -2219,17 +2218,6 @@ fn report_malformed_generics(
2219
2218
) ;
2220
2219
}
2221
2220
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
-
2233
2221
/// Report an ambiguity error, where there were multiple possible resolutions.
2234
2222
///
2235
2223
/// If all `candidates` have the same kind, it's not possible to disambiguate so in this case,
@@ -2243,16 +2231,56 @@ fn ambiguity_error(
2243
2231
emit_error : bool ,
2244
2232
) -> bool {
2245
2233
let mut descrs = FxHashSet :: default ( ) ;
2246
- let kinds = candidates
2234
+ // proc macros can exist in multiple namespaces at once,
2235
+ // so we need to compare DefIds to remove
2236
+ // the candidite in the fn namespace
2237
+ let mut possible_proc_macro_id = None ;
2238
+ let is_proc_macro_crate =
2239
+ cx. tcx . crate_types ( ) == & [ CrateType :: ProcMacro ] ;
2240
+ let mut kinds = candidates
2247
2241
. iter ( )
2248
2242
. map (
2249
2243
|( res, def_id) | {
2250
- if let Some ( def_id) = def_id { Res :: from_def_id ( cx. tcx , * def_id) } else { * res }
2244
+ let r = if let Some ( def_id) = def_id { Res :: from_def_id ( cx. tcx , * def_id) } else { * res } ;
2245
+ if is_proc_macro_crate &&
2246
+ let Res :: Def ( DefKind :: Macro ( _) , id) = r
2247
+ {
2248
+ possible_proc_macro_id = Some ( id) ;
2249
+ }
2250
+ r
2251
2251
} ,
2252
2252
)
2253
- . filter ( |res| descrs. insert ( res. descr ( ) ) )
2254
2253
. collect :: < Vec < _ > > ( ) ;
2255
- if descrs. len ( ) == 1 || refer_to_single_item ( & kinds) {
2254
+ // in order to properly dedup proc macros,
2255
+ // we have to do it in two passes,
2256
+ // completing the full traversal to find
2257
+ // the possible duplicate in the macro namespace,
2258
+ // then another full traversal to eliminate the
2259
+ // candidite in the fn namespace.
2260
+ // thus, we have to do an iteration after
2261
+ // collection is finished.
2262
+ //
2263
+ // as an optimization, we only deduplicate if we're in a proc-macro crate,
2264
+ // and only if we already found something that looks like a proc macro.
2265
+ if is_proc_macro_crate &&
2266
+ let Some ( macro_id) = possible_proc_macro_id
2267
+ {
2268
+ kinds. retain ( |res| {
2269
+ if let Res :: Def ( DefKind :: Fn , fn_id) = res &&
2270
+ macro_id == * fn_id
2271
+ {
2272
+ false
2273
+ } else {
2274
+ true
2275
+ }
2276
+ } ) ;
2277
+ }
2278
+
2279
+ kinds. retain ( |res| {
2280
+ descrs. insert ( res. descr ( ) )
2281
+ } ) ;
2282
+
2283
+ if descrs. len ( ) == 1 {
2256
2284
// There is no way for users to disambiguate at this point, so better return the first
2257
2285
// candidate and not show a warning.
2258
2286
return false ;
0 commit comments