@@ -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,44 @@ 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
+ Some ( tcx. mk_ty ( match prim {
629
+ Bool => ty:: Bool ,
630
+ Str => ty:: Str ,
631
+ Char => ty:: Char ,
632
+ Never => ty:: Never ,
633
+ I8 => ty:: Int ( ty:: IntTy :: I8 ) ,
634
+ I16 => ty:: Int ( ty:: IntTy :: I16 ) ,
635
+ I32 => ty:: Int ( ty:: IntTy :: I32 ) ,
636
+ I64 => ty:: Int ( ty:: IntTy :: I64 ) ,
637
+ I128 => ty:: Int ( ty:: IntTy :: I128 ) ,
638
+ Isize => ty:: Int ( ty:: IntTy :: Isize ) ,
639
+ F32 => ty:: Float ( ty:: FloatTy :: F32 ) ,
640
+ F64 => ty:: Float ( ty:: FloatTy :: F64 ) ,
641
+ U8 => ty:: Uint ( ty:: UintTy :: U8 ) ,
642
+ U16 => ty:: Uint ( ty:: UintTy :: U16 ) ,
643
+ U32 => ty:: Uint ( ty:: UintTy :: U32 ) ,
644
+ U64 => ty:: Uint ( ty:: UintTy :: U64 ) ,
645
+ U128 => ty:: Uint ( ty:: UintTy :: U128 ) ,
646
+ Usize => ty:: Uint ( ty:: UintTy :: Usize ) ,
647
+ //ty::Tuple(tys) if tys.is_empty() => Res::Primitive(Unit),
648
+ //ty::Tuple(_) => Res::Primitive(Tuple),
649
+ //ty::Array(..) => Res::Primitive(Array),
650
+ //ty::Slice(_) => Res::Primitive(Slice),
651
+ //ty::RawPtr(_) => Res::Primitive(RawPointer),
652
+ //ty::Ref(..) => Res::Primitive(Reference),
653
+ //ty::FnDef(..) => panic!("type alias to a function definition"),
654
+ //ty::FnPtr(_) => Res::Primitive(Fn),
655
+ _ => return None ,
656
+ } ) )
657
+ }
658
+
621
659
/// Returns:
622
660
/// - None if no associated item was found
623
661
/// - Some((_, _, Some(_))) if an item was found and should go through a side channel
@@ -632,7 +670,25 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
632
670
let tcx = self . cx . tcx ;
633
671
634
672
match root_res {
635
- Res :: Primitive ( prim) => self . resolve_primitive_associated_item ( prim, ns, item_name) ,
673
+ Res :: Primitive ( prim) => {
674
+ self . resolve_primitive_associated_item ( prim, ns, item_name) . or_else ( || {
675
+ let assoc_item = self
676
+ . primitive_type_to_ty ( prim)
677
+ . map ( |ty| {
678
+ resolve_associated_trait_item ( ty, module_id, item_name, ns, self . cx )
679
+ } )
680
+ . flatten ( ) ;
681
+
682
+ assoc_item. map ( |item| {
683
+ let kind = item. kind ;
684
+ let fragment = UrlFragment :: from_assoc_item ( item_name, kind, false ) ;
685
+ // HACK(jynelson): `clean` expects the type, not the associated item
686
+ // but the disambiguator logic expects the associated item.
687
+ // Store the kind in a side channel so that only the disambiguator logic looks at it.
688
+ ( root_res, fragment, Some ( ( kind. as_def_kind ( ) , item. def_id ) ) )
689
+ } )
690
+ } )
691
+ }
636
692
Res :: Def ( DefKind :: TyAlias , did) => {
637
693
// Resolve the link on the type the alias points to.
638
694
// FIXME: if the associated item is defined directly on the type alias,
@@ -666,8 +722,13 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
666
722
// To handle that properly resolve() would have to support
667
723
// something like [`ambi_fn`](<SomeStruct as SomeTrait>::ambi_fn)
668
724
. or_else ( || {
669
- let item =
670
- resolve_associated_trait_item ( did, module_id, item_name, ns, self . cx ) ;
725
+ let item = resolve_associated_trait_item (
726
+ tcx. type_of ( did) ,
727
+ module_id,
728
+ item_name,
729
+ ns,
730
+ self . cx ,
731
+ ) ;
671
732
debug ! ( "got associated item {:?}" , item) ;
672
733
item
673
734
} ) ;
@@ -767,20 +828,20 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
767
828
/// Given `[std::io::Error::source]`, where `source` is unresolved, this would
768
829
/// find `std::error::Error::source` and return
769
830
/// `<io::Error as error::Error>::source`.
770
- fn resolve_associated_trait_item (
771
- did : DefId ,
831
+ fn resolve_associated_trait_item < ' a > (
832
+ ty : Ty < ' a > ,
772
833
module : DefId ,
773
834
item_name : Symbol ,
774
835
ns : Namespace ,
775
- cx : & mut DocContext < ' _ > ,
836
+ cx : & mut DocContext < ' a > ,
776
837
) -> Option < ty:: AssocItem > {
777
838
// FIXME: this should also consider blanket impls (`impl<T> X for T`). Unfortunately
778
839
// `get_auto_trait_and_blanket_impls` is broken because the caching behavior is wrong. In the
779
840
// meantime, just don't look for these blanket impls.
780
841
781
842
// Next consider explicit impls: `impl MyTrait for MyType`
782
843
// Give precedence to inherent impls.
783
- let traits = traits_implemented_by ( cx, did , module) ;
844
+ let traits = traits_implemented_by ( cx, ty , module) ;
784
845
debug ! ( "considering traits {:?}" , traits) ;
785
846
let mut candidates = traits. iter ( ) . filter_map ( |& trait_| {
786
847
cx. tcx . associated_items ( trait_) . find_by_name_and_namespace (
@@ -799,7 +860,11 @@ fn resolve_associated_trait_item(
799
860
///
800
861
/// NOTE: this cannot be a query because more traits could be available when more crates are compiled!
801
862
/// So it is not stable to serialize cross-crate.
802
- fn traits_implemented_by ( cx : & mut DocContext < ' _ > , type_ : DefId , module : DefId ) -> FxHashSet < DefId > {
863
+ fn traits_implemented_by < ' a > (
864
+ cx : & mut DocContext < ' a > ,
865
+ ty : Ty < ' a > ,
866
+ module : DefId ,
867
+ ) -> FxHashSet < DefId > {
803
868
let mut resolver = cx. resolver . borrow_mut ( ) ;
804
869
let in_scope_traits = cx. module_trait_cache . entry ( module) . or_insert_with ( || {
805
870
resolver. access ( |resolver| {
@@ -813,7 +878,6 @@ fn traits_implemented_by(cx: &mut DocContext<'_>, type_: DefId, module: DefId) -
813
878
} ) ;
814
879
815
880
let tcx = cx. tcx ;
816
- let ty = tcx. type_of ( type_) ;
817
881
let iter = in_scope_traits. iter ( ) . flat_map ( |& trait_| {
818
882
trace ! ( "considering explicit impl for trait {:?}" , trait_) ;
819
883
@@ -826,19 +890,10 @@ fn traits_implemented_by(cx: &mut DocContext<'_>, type_: DefId, module: DefId) -
826
890
"comparing type {} with kind {:?} against type {:?}" ,
827
891
impl_type,
828
892
impl_type. kind( ) ,
829
- type_
893
+ ty
830
894
) ;
831
895
// 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
- } ;
896
+ let saw_impl = impl_type == ty;
842
897
843
898
if saw_impl { Some ( trait_) } else { None }
844
899
} )
0 commit comments