@@ -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,39 @@ 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+ // 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+
621654 /// Returns:
622655 /// - None if no associated item was found
623656 /// - Some((_, _, Some(_))) if an item was found and should go through a side channel
@@ -632,7 +665,25 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
632665 let tcx = self . cx . tcx ;
633666
634667 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+ }
636687 Res :: Def ( DefKind :: TyAlias , did) => {
637688 // Resolve the link on the type the alias points to.
638689 // FIXME: if the associated item is defined directly on the type alias,
@@ -666,8 +717,13 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
666717 // To handle that properly resolve() would have to support
667718 // something like [`ambi_fn`](<SomeStruct as SomeTrait>::ambi_fn)
668719 . 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+ ) ;
671727 debug ! ( "got associated item {:?}" , item) ;
672728 item
673729 } ) ;
@@ -767,20 +823,20 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
767823/// Given `[std::io::Error::source]`, where `source` is unresolved, this would
768824/// find `std::error::Error::source` and return
769825/// `<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 > ,
772828 module : DefId ,
773829 item_name : Symbol ,
774830 ns : Namespace ,
775- cx : & mut DocContext < ' _ > ,
831+ cx : & mut DocContext < ' a > ,
776832) -> Option < ty:: AssocItem > {
777833 // FIXME: this should also consider blanket impls (`impl<T> X for T`). Unfortunately
778834 // `get_auto_trait_and_blanket_impls` is broken because the caching behavior is wrong. In the
779835 // meantime, just don't look for these blanket impls.
780836
781837 // Next consider explicit impls: `impl MyTrait for MyType`
782838 // Give precedence to inherent impls.
783- let traits = traits_implemented_by ( cx, did , module) ;
839+ let traits = traits_implemented_by ( cx, ty , module) ;
784840 debug ! ( "considering traits {:?}" , traits) ;
785841 let mut candidates = traits. iter ( ) . filter_map ( |& trait_| {
786842 cx. tcx . associated_items ( trait_) . find_by_name_and_namespace (
@@ -799,7 +855,11 @@ fn resolve_associated_trait_item(
799855///
800856/// NOTE: this cannot be a query because more traits could be available when more crates are compiled!
801857/// 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 > {
803863 let mut resolver = cx. resolver . borrow_mut ( ) ;
804864 let in_scope_traits = cx. module_trait_cache . entry ( module) . or_insert_with ( || {
805865 resolver. access ( |resolver| {
@@ -813,7 +873,6 @@ fn traits_implemented_by(cx: &mut DocContext<'_>, type_: DefId, module: DefId) -
813873 } ) ;
814874
815875 let tcx = cx. tcx ;
816- let ty = tcx. type_of ( type_) ;
817876 let iter = in_scope_traits. iter ( ) . flat_map ( |& trait_| {
818877 trace ! ( "considering explicit impl for trait {:?}" , trait_) ;
819878
@@ -826,19 +885,10 @@ fn traits_implemented_by(cx: &mut DocContext<'_>, type_: DefId, module: DefId) -
826885 "comparing type {} with kind {:?} against type {:?}" ,
827886 impl_type,
828887 impl_type. kind( ) ,
829- type_
888+ ty
830889 ) ;
831890 // 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;
842892
843893 if saw_impl { Some ( trait_) } else { None }
844894 } )
0 commit comments