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