@@ -87,6 +87,8 @@ use rustc_middle::hir::place::PlaceBase;
8787use rustc_middle:: ty as rustc_ty;
8888use rustc_middle:: ty:: adjustment:: { Adjust , Adjustment , AutoBorrow } ;
8989use rustc_middle:: ty:: binding:: BindingMode ;
90+ use rustc_middle:: ty:: { IntTy , UintTy , FloatTy } ;
91+ use rustc_middle:: ty:: fast_reject:: SimplifiedTypeGen :: * ;
9092use rustc_middle:: ty:: { layout:: IntegerExt , BorrowKind , DefIdTree , Ty , TyCtxt , TypeAndMut , TypeFoldable , UpvarCapture } ;
9193use rustc_semver:: RustcVersion ;
9294use rustc_session:: Session ;
@@ -455,14 +457,6 @@ pub fn path_def_id<'tcx>(cx: &LateContext<'_>, maybe_path: &impl MaybePath<'tcx>
455457/// Resolves a def path like `std::vec::Vec`.
456458/// This function is expensive and should be used sparingly.
457459pub fn def_path_res ( cx : & LateContext < ' _ > , path : & [ & str ] ) -> Res {
458- macro_rules! try_res {
459- ( $e: expr) => {
460- match $e {
461- Some ( e) => e,
462- None => return Res :: Err ,
463- }
464- } ;
465- }
466460 fn item_child_by_name ( tcx : TyCtxt < ' _ > , def_id : DefId , name : & str ) -> Option < Res > {
467461 match tcx. def_kind ( def_id) {
468462 DefKind :: Mod | DefKind :: Enum | DefKind :: Trait => tcx
@@ -479,10 +473,36 @@ pub fn def_path_res(cx: &LateContext<'_>, path: &[&str]) -> Res {
479473 _ => None ,
480474 }
481475 }
482- fn find_primitive ( _tcx : TyCtxt < ' _ > , _name : & str ) -> Option < DefId > {
483- // FIXME: Deal with this without relying on lang items or by only
484- // looking at a single impl.
485- None
476+ fn find_primitive < ' tcx > ( tcx : TyCtxt < ' tcx > , name : & str ) -> impl Iterator < Item = DefId > + ' tcx {
477+ let single = |ty| tcx. incoherent_impls ( ty) . iter ( ) . copied ( ) ;
478+ let empty = || [ ] . iter ( ) . copied ( ) ;
479+ match name {
480+ "bool" => single ( BoolSimplifiedType ) ,
481+ "char" => single ( CharSimplifiedType ) ,
482+ "str" => single ( StrSimplifiedType ) ,
483+ "array" => single ( ArraySimplifiedType ) ,
484+ "slice" => single ( SliceSimplifiedType ) ,
485+ // FIXME: rustdoc documents these two using just `pointer`.
486+ //
487+ // Maybe this is something we should do here too.
488+ "const_ptr" => single ( PtrSimplifiedType ( Mutability :: Not ) ) ,
489+ "mut_ptr" => single ( PtrSimplifiedType ( Mutability :: Mut ) ) ,
490+ "isize" => single ( IntSimplifiedType ( IntTy :: Isize ) ) ,
491+ "i8" => single ( IntSimplifiedType ( IntTy :: I8 ) ) ,
492+ "i16" => single ( IntSimplifiedType ( IntTy :: I16 ) ) ,
493+ "i32" => single ( IntSimplifiedType ( IntTy :: I32 ) ) ,
494+ "i64" => single ( IntSimplifiedType ( IntTy :: I64 ) ) ,
495+ "i128" => single ( IntSimplifiedType ( IntTy :: I128 ) ) ,
496+ "usize" => single ( UintSimplifiedType ( UintTy :: Usize ) ) ,
497+ "u8" => single ( UintSimplifiedType ( UintTy :: U8 ) ) ,
498+ "u16" => single ( UintSimplifiedType ( UintTy :: U16 ) ) ,
499+ "u32" => single ( UintSimplifiedType ( UintTy :: U32 ) ) ,
500+ "u64" => single ( UintSimplifiedType ( UintTy :: U64 ) ) ,
501+ "u128" => single ( UintSimplifiedType ( UintTy :: U128 ) ) ,
502+ "f32" => single ( FloatSimplifiedType ( FloatTy :: F32 ) ) ,
503+ "f64" => single ( FloatSimplifiedType ( FloatTy :: F64 ) ) ,
504+ _ => empty ( ) ,
505+ }
486506 }
487507 fn find_crate ( tcx : TyCtxt < ' _ > , name : & str ) -> Option < DefId > {
488508 tcx. crates ( ( ) )
@@ -500,30 +520,35 @@ pub fn def_path_res(cx: &LateContext<'_>, path: &[&str]) -> Res {
500520 _ => return Res :: Err ,
501521 } ;
502522 let tcx = cx. tcx ;
503- let first = try_res ! (
504- find_primitive( tcx, base)
505- . or_else( || find_crate( tcx, base) )
506- . and_then( |id| item_child_by_name( tcx, id, first) )
507- ) ;
523+ let starts = find_primitive ( tcx, base)
524+ . chain ( find_crate ( tcx, base) )
525+ . flat_map ( |id| item_child_by_name ( tcx, id, first) ) ;
508526
509- let last = path
510- . iter ( )
511- . copied ( )
512- // for each segment, find the child item
513- . try_fold ( first, |res, segment| {
514- let def_id = res. def_id ( ) ;
515- if let Some ( item) = item_child_by_name ( tcx, def_id, segment) {
516- Some ( item)
517- } else if matches ! ( res, Res :: Def ( DefKind :: Enum | DefKind :: Struct , _) ) {
518- // it is not a child item so check inherent impl items
519- tcx. inherent_impls ( def_id)
520- . iter ( )
521- . find_map ( |& impl_def_id| item_child_by_name ( tcx, impl_def_id, segment) )
522- } else {
523- None
524- }
525- } ) ;
526- try_res ! ( last) . expect_non_local ( )
527+ for first in starts {
528+ let last = path
529+ . iter ( )
530+ . copied ( )
531+ // for each segment, find the child item
532+ . try_fold ( first, |res, segment| {
533+ let def_id = res. def_id ( ) ;
534+ if let Some ( item) = item_child_by_name ( tcx, def_id, segment) {
535+ Some ( item)
536+ } else if matches ! ( res, Res :: Def ( DefKind :: Enum | DefKind :: Struct , _) ) {
537+ // it is not a child item so check inherent impl items
538+ tcx. inherent_impls ( def_id)
539+ . iter ( )
540+ . find_map ( |& impl_def_id| item_child_by_name ( tcx, impl_def_id, segment) )
541+ } else {
542+ None
543+ }
544+ } ) ;
545+
546+ if let Some ( last) = last {
547+ return last;
548+ }
549+ }
550+
551+ Res :: Err
527552}
528553
529554/// Convenience function to get the `DefId` of a trait by path.
0 commit comments