@@ -13,7 +13,7 @@ use rustc_hir::def::{
1313 PerNS ,
1414} ;
1515use rustc_hir:: def_id:: { CrateNum , DefId } ;
16- use rustc_middle:: ty:: TyCtxt ;
16+ use rustc_middle:: ty:: { Ty , TyCtxt } ;
1717use rustc_middle:: { bug, span_bug, ty} ;
1818use rustc_resolve:: ParentScope ;
1919use rustc_session:: lint:: Lint ;
@@ -618,6 +618,44 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
618618 } )
619619 }
620620
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+
621659 /// Returns:
622660 /// - None if no associated item was found
623661 /// - Some((_, _, Some(_))) if an item was found and should go through a side channel
@@ -632,7 +670,25 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
632670 let tcx = self . cx . tcx ;
633671
634672 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+ }
636692 Res :: Def ( DefKind :: TyAlias , did) => {
637693 // Resolve the link on the type the alias points to.
638694 // FIXME: if the associated item is defined directly on the type alias,
@@ -666,8 +722,13 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
666722 // To handle that properly resolve() would have to support
667723 // something like [`ambi_fn`](<SomeStruct as SomeTrait>::ambi_fn)
668724 . 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+ ) ;
671732 debug ! ( "got associated item {:?}" , item) ;
672733 item
673734 } ) ;
@@ -767,20 +828,20 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
767828/// Given `[std::io::Error::source]`, where `source` is unresolved, this would
768829/// find `std::error::Error::source` and return
769830/// `<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 > ,
772833 module : DefId ,
773834 item_name : Symbol ,
774835 ns : Namespace ,
775- cx : & mut DocContext < ' _ > ,
836+ cx : & mut DocContext < ' a > ,
776837) -> Option < ty:: AssocItem > {
777838 // FIXME: this should also consider blanket impls (`impl<T> X for T`). Unfortunately
778839 // `get_auto_trait_and_blanket_impls` is broken because the caching behavior is wrong. In the
779840 // meantime, just don't look for these blanket impls.
780841
781842 // Next consider explicit impls: `impl MyTrait for MyType`
782843 // Give precedence to inherent impls.
783- let traits = traits_implemented_by ( cx, did , module) ;
844+ let traits = traits_implemented_by ( cx, ty , module) ;
784845 debug ! ( "considering traits {:?}" , traits) ;
785846 let mut candidates = traits. iter ( ) . filter_map ( |& trait_| {
786847 cx. tcx . associated_items ( trait_) . find_by_name_and_namespace (
@@ -799,7 +860,11 @@ fn resolve_associated_trait_item(
799860///
800861/// NOTE: this cannot be a query because more traits could be available when more crates are compiled!
801862/// 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 > {
803868 let mut resolver = cx. resolver . borrow_mut ( ) ;
804869 let in_scope_traits = cx. module_trait_cache . entry ( module) . or_insert_with ( || {
805870 resolver. access ( |resolver| {
@@ -813,7 +878,6 @@ fn traits_implemented_by(cx: &mut DocContext<'_>, type_: DefId, module: DefId) -
813878 } ) ;
814879
815880 let tcx = cx. tcx ;
816- let ty = tcx. type_of ( type_) ;
817881 let iter = in_scope_traits. iter ( ) . flat_map ( |& trait_| {
818882 trace ! ( "considering explicit impl for trait {:?}" , trait_) ;
819883
@@ -826,19 +890,10 @@ fn traits_implemented_by(cx: &mut DocContext<'_>, type_: DefId, module: DefId) -
826890 "comparing type {} with kind {:?} against type {:?}" ,
827891 impl_type,
828892 impl_type. kind( ) ,
829- type_
893+ ty
830894 ) ;
831895 // 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;
842897
843898 if saw_impl { Some ( trait_) } else { None }
844899 } )
0 commit comments