@@ -13,7 +13,7 @@ use rustc_hir::def::{
13
13
PerNS ,
14
14
} ;
15
15
use rustc_hir:: def_id:: { CrateNum , DefId } ;
16
- use rustc_middle:: ty:: TyCtxt ;
16
+ use rustc_middle:: ty:: { Ty , TyCtxt } ;
17
17
use rustc_middle:: { bug, span_bug, ty} ;
18
18
use rustc_resolve:: ParentScope ;
19
19
use rustc_session:: lint:: Lint ;
@@ -618,6 +618,39 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
618
618
} )
619
619
}
620
620
621
+ /// Convert a PrimitiveType to a Ty, where possible.
622
+ ///
623
+ /// This is used for resolving trait impls for primitives
624
+ fn primitive_type_to_ty ( & mut self , prim : PrimitiveType ) -> Option < Ty < ' tcx > > {
625
+ use PrimitiveType :: * ;
626
+ let tcx = self . cx . tcx ;
627
+
628
+ // FIXME: Only simple types are supported here, see if we can support
629
+ // other types such as Tuple, Array, Slice, etc.
630
+ // See https://github.com/rust-lang/rust/issues/90703#issuecomment-1004263455
631
+ Some ( tcx. mk_ty ( match prim {
632
+ Bool => ty:: Bool ,
633
+ Str => ty:: Str ,
634
+ Char => ty:: Char ,
635
+ Never => ty:: Never ,
636
+ I8 => ty:: Int ( ty:: IntTy :: I8 ) ,
637
+ I16 => ty:: Int ( ty:: IntTy :: I16 ) ,
638
+ I32 => ty:: Int ( ty:: IntTy :: I32 ) ,
639
+ I64 => ty:: Int ( ty:: IntTy :: I64 ) ,
640
+ I128 => ty:: Int ( ty:: IntTy :: I128 ) ,
641
+ Isize => ty:: Int ( ty:: IntTy :: Isize ) ,
642
+ F32 => ty:: Float ( ty:: FloatTy :: F32 ) ,
643
+ F64 => ty:: Float ( ty:: FloatTy :: F64 ) ,
644
+ U8 => ty:: Uint ( ty:: UintTy :: U8 ) ,
645
+ U16 => ty:: Uint ( ty:: UintTy :: U16 ) ,
646
+ U32 => ty:: Uint ( ty:: UintTy :: U32 ) ,
647
+ U64 => ty:: Uint ( ty:: UintTy :: U64 ) ,
648
+ U128 => ty:: Uint ( ty:: UintTy :: U128 ) ,
649
+ Usize => ty:: Uint ( ty:: UintTy :: Usize ) ,
650
+ _ => return None ,
651
+ } ) )
652
+ }
653
+
621
654
/// Returns:
622
655
/// - None if no associated item was found
623
656
/// - Some((_, _, Some(_))) if an item was found and should go through a side channel
@@ -632,7 +665,25 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
632
665
let tcx = self . cx . tcx ;
633
666
634
667
match root_res {
635
- Res :: Primitive ( prim) => self . resolve_primitive_associated_item ( prim, ns, item_name) ,
668
+ Res :: Primitive ( prim) => {
669
+ self . resolve_primitive_associated_item ( prim, ns, item_name) . or_else ( || {
670
+ let assoc_item = self
671
+ . primitive_type_to_ty ( prim)
672
+ . map ( |ty| {
673
+ resolve_associated_trait_item ( ty, module_id, item_name, ns, self . cx )
674
+ } )
675
+ . flatten ( ) ;
676
+
677
+ assoc_item. map ( |item| {
678
+ let kind = item. kind ;
679
+ let fragment = UrlFragment :: from_assoc_item ( item_name, kind, false ) ;
680
+ // HACK(jynelson): `clean` expects the type, not the associated item
681
+ // but the disambiguator logic expects the associated item.
682
+ // Store the kind in a side channel so that only the disambiguator logic looks at it.
683
+ ( root_res, fragment, Some ( ( kind. as_def_kind ( ) , item. def_id ) ) )
684
+ } )
685
+ } )
686
+ }
636
687
Res :: Def ( DefKind :: TyAlias , did) => {
637
688
// Resolve the link on the type the alias points to.
638
689
// FIXME: if the associated item is defined directly on the type alias,
@@ -666,8 +717,13 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
666
717
// To handle that properly resolve() would have to support
667
718
// something like [`ambi_fn`](<SomeStruct as SomeTrait>::ambi_fn)
668
719
. or_else ( || {
669
- let item =
670
- resolve_associated_trait_item ( did, module_id, item_name, ns, self . cx ) ;
720
+ let item = resolve_associated_trait_item (
721
+ tcx. type_of ( did) ,
722
+ module_id,
723
+ item_name,
724
+ ns,
725
+ self . cx ,
726
+ ) ;
671
727
debug ! ( "got associated item {:?}" , item) ;
672
728
item
673
729
} ) ;
@@ -767,20 +823,20 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
767
823
/// Given `[std::io::Error::source]`, where `source` is unresolved, this would
768
824
/// find `std::error::Error::source` and return
769
825
/// `<io::Error as error::Error>::source`.
770
- fn resolve_associated_trait_item (
771
- did : DefId ,
826
+ fn resolve_associated_trait_item < ' a > (
827
+ ty : Ty < ' a > ,
772
828
module : DefId ,
773
829
item_name : Symbol ,
774
830
ns : Namespace ,
775
- cx : & mut DocContext < ' _ > ,
831
+ cx : & mut DocContext < ' a > ,
776
832
) -> Option < ty:: AssocItem > {
777
833
// FIXME: this should also consider blanket impls (`impl<T> X for T`). Unfortunately
778
834
// `get_auto_trait_and_blanket_impls` is broken because the caching behavior is wrong. In the
779
835
// meantime, just don't look for these blanket impls.
780
836
781
837
// Next consider explicit impls: `impl MyTrait for MyType`
782
838
// Give precedence to inherent impls.
783
- let traits = traits_implemented_by ( cx, did , module) ;
839
+ let traits = traits_implemented_by ( cx, ty , module) ;
784
840
debug ! ( "considering traits {:?}" , traits) ;
785
841
let mut candidates = traits. iter ( ) . filter_map ( |& trait_| {
786
842
cx. tcx . associated_items ( trait_) . find_by_name_and_namespace (
@@ -799,7 +855,11 @@ fn resolve_associated_trait_item(
799
855
///
800
856
/// NOTE: this cannot be a query because more traits could be available when more crates are compiled!
801
857
/// So it is not stable to serialize cross-crate.
802
- fn traits_implemented_by ( cx : & mut DocContext < ' _ > , type_ : DefId , module : DefId ) -> FxHashSet < DefId > {
858
+ fn traits_implemented_by < ' a > (
859
+ cx : & mut DocContext < ' a > ,
860
+ ty : Ty < ' a > ,
861
+ module : DefId ,
862
+ ) -> FxHashSet < DefId > {
803
863
let mut resolver = cx. resolver . borrow_mut ( ) ;
804
864
let in_scope_traits = cx. module_trait_cache . entry ( module) . or_insert_with ( || {
805
865
resolver. access ( |resolver| {
@@ -813,7 +873,6 @@ fn traits_implemented_by(cx: &mut DocContext<'_>, type_: DefId, module: DefId) -
813
873
} ) ;
814
874
815
875
let tcx = cx. tcx ;
816
- let ty = tcx. type_of ( type_) ;
817
876
let iter = in_scope_traits. iter ( ) . flat_map ( |& trait_| {
818
877
trace ! ( "considering explicit impl for trait {:?}" , trait_) ;
819
878
@@ -826,19 +885,10 @@ fn traits_implemented_by(cx: &mut DocContext<'_>, type_: DefId, module: DefId) -
826
885
"comparing type {} with kind {:?} against type {:?}" ,
827
886
impl_type,
828
887
impl_type. kind( ) ,
829
- type_
888
+ ty
830
889
) ;
831
890
// Fast path: if this is a primitive simple `==` will work
832
- let saw_impl = impl_type == ty
833
- || match impl_type. kind ( ) {
834
- // Check if these are the same def_id
835
- ty:: Adt ( def, _) => {
836
- debug ! ( "adt def_id: {:?}" , def. did) ;
837
- def. did == type_
838
- }
839
- ty:: Foreign ( def_id) => * def_id == type_,
840
- _ => false ,
841
- } ;
891
+ let saw_impl = impl_type == ty;
842
892
843
893
if saw_impl { Some ( trait_) } else { None }
844
894
} )
0 commit comments