@@ -82,7 +82,7 @@ use hir::def::Def;
82
82
use hir:: def_id:: DefId ;
83
83
use infer:: { self , TypeOrigin } ;
84
84
use middle:: region;
85
- use ty:: { self , TyCtxt , TypeFoldable } ;
85
+ use ty:: { self , ImplOrTraitItem , Ty , TyCtxt , TypeFoldable } ;
86
86
use ty:: { Region , ReFree } ;
87
87
use ty:: error:: TypeError ;
88
88
@@ -548,7 +548,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
548
548
{
549
549
let expected_found = match values {
550
550
None => None ,
551
- Some ( values) => match self . values_str ( & values) {
551
+ Some ( ref values) => match self . values_str ( & values) {
552
552
Some ( ( expected, found) ) => Some ( ( expected, found) ) ,
553
553
None => {
554
554
// Derived error. Cancel the emitter.
@@ -581,6 +581,27 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
581
581
diag. note_expected_found ( & "type" , & expected, & found) ;
582
582
}
583
583
}
584
+
585
+ if let Some ( ( found, ( expected_ty, _) ) ) = self . get_ids ( values) {
586
+ // look for expected with found id
587
+ self . tcx . populate_inherent_implementations_for_type_if_necessary ( found) ;
588
+ if let Some ( impl_infos) = self . tcx . inherent_impls . borrow ( ) . get ( & found) {
589
+ let mut methods = Vec :: new ( ) ;
590
+ for impl_ in impl_infos {
591
+ methods. append ( & mut self . tcx
592
+ . impl_or_trait_items ( * impl_)
593
+ . iter ( )
594
+ . map ( |& did| self . tcx . impl_or_trait_item ( did) )
595
+ . filter ( |x| {
596
+ self . matches_return_type ( x, & expected_ty)
597
+ } )
598
+ . collect ( ) ) ;
599
+ }
600
+ for method in methods {
601
+ println ! ( "==> {:?}" , method. name( ) ) ;
602
+ }
603
+ }
604
+ }
584
605
}
585
606
586
607
diag. span_label ( span, & terr) ;
@@ -621,6 +642,60 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
621
642
}
622
643
}
623
644
645
+ fn matches_return_type ( & self , method : & ImplOrTraitItem < ' tcx > , expected : & ty:: Ty < ' tcx > ) -> bool {
646
+ match * method {
647
+ ImplOrTraitItem :: MethodTraitItem ( ref x) => {
648
+ self . can_sub_types ( x. fty . sig . skip_binder ( ) . output , expected) . is_ok ( )
649
+ }
650
+ _ => false ,
651
+ }
652
+ }
653
+
654
+ fn get_id ( & self , ty : Ty < ' tcx > ) -> Option < DefId > {
655
+ match ty. sty {
656
+ ty:: TyTrait ( box ref data) => Some ( data. principal . def_id ( ) ) ,
657
+ ty:: TyAdt ( def, _) => Some ( def. did ) ,
658
+ ty:: TyBox ( ref ty) => self . get_id ( * ty) , // since we don't want box's methods by type's
659
+ ty:: TyChar => self . tcx . lang_items . char_impl ( ) ,
660
+ ty:: TyStr => self . tcx . lang_items . str_impl ( ) ,
661
+ ty:: TySlice ( _) => self . tcx . lang_items . slice_impl ( ) ,
662
+ ty:: TyRawPtr ( ty:: TypeAndMut { ty : _, mutbl : hir:: MutImmutable } ) => {
663
+ self . tcx . lang_items . const_ptr_impl ( )
664
+ }
665
+ ty:: TyRawPtr ( ty:: TypeAndMut { ty : _, mutbl : hir:: MutMutable } ) => {
666
+ self . tcx . lang_items . mut_ptr_impl ( )
667
+ }
668
+ ty:: TyInt ( ast:: IntTy :: I8 ) => self . tcx . lang_items . i8_impl ( ) ,
669
+ ty:: TyInt ( ast:: IntTy :: I16 ) => self . tcx . lang_items . i16_impl ( ) ,
670
+ ty:: TyInt ( ast:: IntTy :: I32 ) => self . tcx . lang_items . i32_impl ( ) ,
671
+ ty:: TyInt ( ast:: IntTy :: I64 ) => self . tcx . lang_items . i64_impl ( ) ,
672
+ ty:: TyInt ( ast:: IntTy :: Is ) => self . tcx . lang_items . isize_impl ( ) ,
673
+ ty:: TyUint ( ast:: UintTy :: U8 ) => self . tcx . lang_items . u8_impl ( ) ,
674
+ ty:: TyUint ( ast:: UintTy :: U16 ) => self . tcx . lang_items . u16_impl ( ) ,
675
+ ty:: TyUint ( ast:: UintTy :: U32 ) => self . tcx . lang_items . u32_impl ( ) ,
676
+ ty:: TyUint ( ast:: UintTy :: U64 ) => self . tcx . lang_items . u64_impl ( ) ,
677
+ ty:: TyUint ( ast:: UintTy :: Us ) => self . tcx . lang_items . usize_impl ( ) ,
678
+ ty:: TyFloat ( ast:: FloatTy :: F32 ) => self . tcx . lang_items . f32_impl ( ) ,
679
+ ty:: TyFloat ( ast:: FloatTy :: F64 ) => self . tcx . lang_items . f64_impl ( ) ,
680
+ _ => None ,
681
+ }
682
+ }
683
+
684
+ // Yep, returned value super ugly. it'll certainly become `Option<(DefId, ty::Ty<'tcx>)>`
685
+ // in a close future. Or maybe a struct?
686
+ fn get_ids ( & self , values : Option < ValuePairs < ' tcx > > ) -> Option < ( DefId , ( ty:: Ty < ' tcx > , DefId ) ) > {
687
+ match values {
688
+ // for now, only handling non trait types
689
+ Some ( infer:: Types ( ref exp_found) ) => {
690
+ match ( self . get_id ( exp_found. found ) , self . get_id ( exp_found. expected ) ) {
691
+ ( Some ( found) , Some ( expected) ) => Some ( ( found, ( exp_found. expected , expected) ) ) ,
692
+ _ => None ,
693
+ }
694
+ }
695
+ _ => None ,
696
+ }
697
+ }
698
+
624
699
fn expected_found_str < T : fmt:: Display + TypeFoldable < ' tcx > > (
625
700
& self ,
626
701
exp_found : & ty:: error:: ExpectedFound < T > )
0 commit comments