@@ -46,6 +46,9 @@ pub fn collect_intra_doc_links(krate: Crate, cx: &DocContext<'_>) -> Crate {
46
46
enum ErrorKind {
47
47
ResolutionFailure ,
48
48
AnchorFailure ( & ' static str ) ,
49
+ Ambiguous {
50
+ candidates : Vec < Res > ,
51
+ }
49
52
}
50
53
51
54
struct LinkCollector < ' a , ' tcx > {
@@ -291,7 +294,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
291
294
let ty = cx. tcx . type_of ( did) ;
292
295
// Checks if item_name belongs to `impl SomeItem`
293
296
let impls = crate :: clean:: get_auto_trait_and_blanket_impls ( cx, ty, did) ;
294
- let impl_kind = impls
297
+ let candidates : Vec < _ > = impls
295
298
. flat_map ( |impl_outer| {
296
299
match impl_outer. inner {
297
300
ImplItem ( impl_) => {
@@ -306,8 +309,11 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
306
309
// but provided methods come directly from `tcx`.
307
310
// Fortunately, we don't need the whole method, we just need to know
308
311
// what kind of associated item it is.
309
- assoc. inner . as_assoc_kind ( )
310
- . expect ( "inner items for a trait should be associated items" )
312
+ (
313
+ assoc. def_id ,
314
+ assoc. inner . as_assoc_kind ( )
315
+ . expect ( "inner items for a trait should be associated items" )
316
+ )
311
317
} )
312
318
// TODO: this collect seems a shame
313
319
. collect ( )
@@ -322,16 +328,23 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
322
328
// TODO: this is wrong, it should look at the trait, not the impl
323
329
cx. tcx . associated_items ( impl_outer. def_id )
324
330
. filter_by_name ( cx. tcx , Ident :: with_dummy_span ( item_name) , impl_outer. def_id )
325
- . map ( |assoc| assoc. kind )
331
+ . map ( |assoc| ( assoc. def_id , assoc . kind ) )
326
332
// TODO: this collect seems a shame
327
333
. collect :: < Vec < _ > > ( )
328
334
}
329
335
}
330
336
_ => panic ! ( "get_impls returned something that wasn't an impl" ) ,
331
337
}
332
338
} )
333
- // TODO: give a warning if this is ambiguous
334
- . next ( ) ;
339
+ . chain ( cx. tcx . all_impls ( ) )
340
+ . collect ( ) ;
341
+ if candidates. len ( ) > 1 {
342
+ let candidates = candidates. into_iter ( )
343
+ . map ( |( def_id, kind) | Res :: Def ( kind. as_def_kind ( ) , def_id) )
344
+ . collect ( ) ;
345
+ return Err ( ErrorKind :: Ambiguous { candidates } ) ;
346
+ }
347
+ let impl_kind = candidates. into_iter ( ) . next ( ) . map ( |( _, kind) | kind) ;
335
348
// TODO: is this necessary? It doesn't look right, and also only works for local items
336
349
let trait_kind = self . cx . as_local_hir_id ( item. def_id )
337
350
. and_then ( |item_hir| {
@@ -694,6 +707,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
694
707
}
695
708
696
709
match kind {
710
+ // TODO: reduce this duplicate code
697
711
Some ( ns @ ValueNS ) => {
698
712
match self . resolve (
699
713
path_str,
@@ -716,6 +730,17 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
716
730
anchor_failure ( cx, & item, & ori_link, & dox, link_range, msg) ;
717
731
continue ;
718
732
}
733
+ Err ( ErrorKind :: Ambiguous { candidates } ) => {
734
+ ambiguity_error (
735
+ cx,
736
+ & item,
737
+ path_str,
738
+ & dox,
739
+ link_range,
740
+ candidates. into_iter ( ) . map ( |res| ( res, TypeNS ) ) . collect ( ) ,
741
+ ) ;
742
+ continue ;
743
+ }
719
744
}
720
745
}
721
746
Some ( ns @ TypeNS ) => {
@@ -738,6 +763,17 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
738
763
anchor_failure ( cx, & item, & ori_link, & dox, link_range, msg) ;
739
764
continue ;
740
765
}
766
+ Err ( ErrorKind :: Ambiguous { candidates } ) => {
767
+ ambiguity_error (
768
+ cx,
769
+ & item,
770
+ path_str,
771
+ & dox,
772
+ link_range,
773
+ candidates. into_iter ( ) . map ( |res| ( res, TypeNS ) ) . collect ( ) ,
774
+ ) ;
775
+ continue ;
776
+ }
741
777
}
742
778
}
743
779
None => {
@@ -809,13 +845,18 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
809
845
if is_derive_trait_collision ( & candidates) {
810
846
candidates. macro_ns = None ;
811
847
}
848
+ let candidates = candidates. map ( |opt| opt. map ( |( res, _) | res) ) ;
849
+ let candidates = [ TypeNS , ValueNS , MacroNS ]
850
+ . iter ( )
851
+ . filter_map ( |& ns| candidates[ ns] . map ( |res| ( res, ns) ) )
852
+ . collect ( ) ;
812
853
ambiguity_error (
813
854
cx,
814
855
& item,
815
856
path_str,
816
857
& dox,
817
858
link_range,
818
- candidates. map ( |candidate| candidate . map ( | ( res , _ ) | res ) ) ,
859
+ candidates,
819
860
) ;
820
861
continue ;
821
862
}
@@ -1001,7 +1042,7 @@ fn ambiguity_error(
1001
1042
path_str : & str ,
1002
1043
dox : & str ,
1003
1044
link_range : Option < Range < usize > > ,
1004
- candidates : PerNS < Option < Res > > ,
1045
+ candidates : Vec < ( Res , Namespace ) > ,
1005
1046
) {
1006
1047
let hir_id = match cx. as_local_hir_id ( item. def_id ) {
1007
1048
Some ( hir_id) => hir_id,
@@ -1020,10 +1061,6 @@ fn ambiguity_error(
1020
1061
|lint| {
1021
1062
let mut msg = format ! ( "`{}` is " , path_str) ;
1022
1063
1023
- let candidates = [ TypeNS , ValueNS , MacroNS ]
1024
- . iter ( )
1025
- . filter_map ( |& ns| candidates[ ns] . map ( |res| ( res, ns) ) )
1026
- . collect :: < Vec < _ > > ( ) ;
1027
1064
match candidates. as_slice ( ) {
1028
1065
[ ( first_def, _) , ( second_def, _) ] => {
1029
1066
msg += & format ! (
0 commit comments