@@ -87,6 +87,8 @@ use rustc_middle::hir::place::PlaceBase;
87
87
use rustc_middle:: ty as rustc_ty;
88
88
use rustc_middle:: ty:: adjustment:: { Adjust , Adjustment , AutoBorrow } ;
89
89
use rustc_middle:: ty:: binding:: BindingMode ;
90
+ use rustc_middle:: ty:: { IntTy , UintTy , FloatTy } ;
91
+ use rustc_middle:: ty:: fast_reject:: SimplifiedTypeGen :: * ;
90
92
use rustc_middle:: ty:: { layout:: IntegerExt , BorrowKind , DefIdTree , Ty , TyCtxt , TypeAndMut , TypeFoldable , UpvarCapture } ;
91
93
use rustc_semver:: RustcVersion ;
92
94
use rustc_session:: Session ;
@@ -455,14 +457,6 @@ pub fn path_def_id<'tcx>(cx: &LateContext<'_>, maybe_path: &impl MaybePath<'tcx>
455
457
/// Resolves a def path like `std::vec::Vec`.
456
458
/// This function is expensive and should be used sparingly.
457
459
pub 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
- }
466
460
fn item_child_by_name ( tcx : TyCtxt < ' _ > , def_id : DefId , name : & str ) -> Option < Res > {
467
461
match tcx. def_kind ( def_id) {
468
462
DefKind :: Mod | DefKind :: Enum | DefKind :: Trait => tcx
@@ -479,10 +473,36 @@ pub fn def_path_res(cx: &LateContext<'_>, path: &[&str]) -> Res {
479
473
_ => None ,
480
474
}
481
475
}
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
+ }
486
506
}
487
507
fn find_crate ( tcx : TyCtxt < ' _ > , name : & str ) -> Option < DefId > {
488
508
tcx. crates ( ( ) )
@@ -500,30 +520,35 @@ pub fn def_path_res(cx: &LateContext<'_>, path: &[&str]) -> Res {
500
520
_ => return Res :: Err ,
501
521
} ;
502
522
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) ) ;
508
526
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
527
552
}
528
553
529
554
/// Convenience function to get the `DefId` of a trait by path.
0 commit comments