@@ -83,7 +83,7 @@ use hir::def_id::DefId;
8383use infer;
8484use middle:: region;
8585use traits:: { ObligationCause , ObligationCauseCode } ;
86- use ty:: { self , TyCtxt , TypeFoldable } ;
86+ use ty:: { self , ImplOrTraitItem , Ty , TyCtxt , TypeFoldable } ;
8787use ty:: { Region , ReFree } ;
8888use ty:: error:: TypeError ;
8989
@@ -549,7 +549,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
549549 {
550550 let expected_found = match values {
551551 None => None ,
552- Some ( values) => match self . values_str ( & values) {
552+ Some ( ref values) => match self . values_str ( & values) {
553553 Some ( ( expected, found) ) => Some ( ( expected, found) ) ,
554554 None => {
555555 // Derived error. Cancel the emitter.
@@ -582,6 +582,27 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
582582 diag. note_expected_found ( & "type" , & expected, & found) ;
583583 }
584584 }
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+ }
585606 }
586607
587608 diag. span_label ( span, & terr) ;
@@ -622,6 +643,60 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
622643 }
623644 }
624645
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+
625700 fn expected_found_str < T : fmt:: Display + TypeFoldable < ' tcx > > (
626701 & self ,
627702 exp_found : & ty:: error:: ExpectedFound < T > )
0 commit comments