@@ -455,124 +455,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
455455            InferSourceKind :: LetBinding  {  insert_span,  pattern_name,  ty,  def_id,  hir_id }  => { 
456456                let  mut  paths = vec ! [ ] ; 
457457                if  let  Some ( def_id)  = def_id
458-                     && let  name = self . infcx . tcx . item_name ( def_id) 
459458                    && let  Some ( hir_id)  = hir_id
460459                    && let  expr = self . infcx . tcx . hir ( ) . expect_expr ( hir_id) 
461460                    && let  hir:: ExprKind :: MethodCall ( _,  rcvr,  _,  _)  = expr. kind 
462461                    && let  Some ( ty)  = typeck_results. node_type_opt ( rcvr. hir_id ) 
463462                { 
464-                     // Look for all the possible implementations to suggest, otherwise we'll show 
465-                     // just suggest the syntax for the fully qualified path with placeholders. 
466-                     self . infcx . tcx . for_each_relevant_impl ( 
467-                         self . infcx . tcx . parent ( def_id) ,  // Trait `DefId` 
468-                         ty,                             // `Self` type 
469-                         |impl_def_id| { 
470-                             let  impl_args = ty:: GenericArgs :: for_item ( 
471-                                 self . infcx . tcx , 
472-                                 impl_def_id, 
473-                                 |param,  _| { 
474-                                     // We don't want to name the arguments, we just want to give an 
475-                                     // idea of what the syntax is. 
476-                                     match  param. kind  { 
477-                                         ty:: GenericParamDefKind :: Lifetime  => { 
478-                                             self . infcx . tcx . lifetimes . re_erased . into ( ) 
479-                                         } 
480-                                         ty:: GenericParamDefKind :: Type  {  .. }  => { 
481-                                             self . next_ty_var ( DUMMY_SP ) . into ( ) 
482-                                         } 
483-                                         ty:: GenericParamDefKind :: Const  {  .. }  => { 
484-                                             self . next_const_var ( DUMMY_SP ) . into ( ) 
485-                                         } 
486-                                     } 
487-                                 } , 
488-                             ) ; 
489-                             let  impl_trait_ref = self 
490-                                 . infcx 
491-                                 . tcx 
492-                                 . impl_trait_ref ( impl_def_id) 
493-                                 . unwrap ( ) 
494-                                 . instantiate ( self . infcx . tcx ,  impl_args) ; 
495-                             let  impl_self_ty = impl_trait_ref. self_ty ( ) ; 
496-                             if  self . infcx . can_eq ( param_env,  impl_self_ty,  ty)  { 
497-                                 // The expr's self type could conform to this impl's self type. 
498-                             }  else  { 
499-                                 // Nope, don't bother. 
500-                                 return ; 
501-                             } 
502-                             let  assocs = self . infcx . tcx . associated_items ( impl_def_id) ; 
503- 
504-                             if  self 
505-                                 . infcx 
506-                                 . tcx 
507-                                 . is_diagnostic_item ( sym:: blanket_into_impl,  impl_def_id) 
508-                                 && let  Some ( did)  = self . infcx . tcx . get_diagnostic_item ( sym:: From ) 
509-                             { 
510-                                 let  mut  found = false ; 
511-                                 self . infcx . tcx . for_each_impl ( did,  |impl_def_id| { 
512-                                     // We had an `<A as Into<B>::into` and we've hit the blanket 
513-                                     // impl for `From<A>`. So we try and look for the right `From` 
514-                                     // impls that *would* apply. We *could* do this in a generalized 
515-                                     // version by evaluating the `where` clauses, but that would be 
516-                                     // way too involved to implement. Instead we special case the 
517-                                     // arguably most common case of `expr.into()`. 
518-                                     let  Some ( header)  =
519-                                         self . infcx . tcx . impl_trait_header ( impl_def_id) 
520-                                     else  { 
521-                                         return ; 
522-                                     } ; 
523-                                     let  target = header. trait_ref . skip_binder ( ) . args . type_at ( 0 ) ; 
524-                                     let  _ty = header. trait_ref . skip_binder ( ) . args . type_at ( 1 ) ; 
525-                                     if  _ty == ty { 
526-                                         paths. push ( format ! ( "{target}" ) ) ; 
527-                                         found = true ; 
528-                                     } 
529-                                 } ) ; 
530-                                 if  found { 
531-                                     return ; 
532-                                 } 
533-                             } 
534- 
535-                             // We're at the `impl` level, but we want to get the same method we 
536-                             // called *on this `impl`*, in order to get the right DefId and args. 
537-                             let  Some ( assoc)  = assocs. filter_by_name_unhygienic ( name) . next ( )  else  { 
538-                                 // The method isn't in this `impl`? Not useful to us then. 
539-                                 return ; 
540-                             } ; 
541-                             let  Some ( trait_assoc_item)  = assoc. trait_item_def_id  else  { 
542-                                 return ; 
543-                             } ; 
544-                             // Let's ignore the generic params and replace them with `_` in the 
545-                             // suggested path. 
546-                             let  trait_assoc_substs = impl_trait_ref. args . extend_to ( 
547-                                 self . infcx . tcx , 
548-                                 trait_assoc_item, 
549-                                 |def,  _| { 
550-                                     // We don't want to name the arguments, we just want to give an 
551-                                     // idea of what the syntax is. 
552-                                     match  def. kind  { 
553-                                         ty:: GenericParamDefKind :: Lifetime  => { 
554-                                             self . infcx . tcx . lifetimes . re_erased . into ( ) 
555-                                         } 
556-                                         ty:: GenericParamDefKind :: Type  {  .. }  => { 
557-                                             self . next_ty_var ( DUMMY_SP ) . into ( ) 
558-                                         } 
559-                                         ty:: GenericParamDefKind :: Const  {  .. }  => { 
560-                                             self . next_const_var ( DUMMY_SP ) . into ( ) 
561-                                         } 
562-                                     } 
563-                                 } , 
564-                             ) ; 
565-                             let  identity_method =
566-                                 impl_args. rebase_onto ( self . infcx . tcx ,  def_id,  trait_assoc_substs) ; 
567-                             let  fn_sig = self 
568-                                 . infcx 
569-                                 . tcx 
570-                                 . fn_sig ( def_id) 
571-                                 . instantiate ( self . infcx . tcx ,  identity_method) ; 
572-                             let  ret = fn_sig. skip_binder ( ) . output ( ) ; 
573-                             paths. push ( format ! ( "{ret}" ) ) ; 
574-                         } , 
575-                     ) ; 
463+                     paths = self . get_suggestions ( ty,  def_id,  true ,  param_env,  None ) ; 
576464                } 
577465
578466                if  paths. is_empty ( )  { 
@@ -697,114 +585,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
697585                        _ => "" , 
698586                    } ; 
699587
700-                     let  mut  paths = vec ! [ ] ; 
701-                     let  name = self . infcx . tcx . item_name ( def_id) ; 
702588                    // Look for all the possible implementations to suggest, otherwise we'll show 
703589                    // just suggest the syntax for the fully qualified path with placeholders. 
704-                     self . infcx . tcx . for_each_relevant_impl ( 
705-                         self . infcx . tcx . parent ( def_id) ,  // Trait `DefId` 
706-                         args. type_at ( 0 ) ,                // `Self` type 
707-                         |impl_def_id| { 
708-                             let  impl_args = ty:: GenericArgs :: for_item ( 
709-                                 self . infcx . tcx , 
710-                                 impl_def_id, 
711-                                 |param,  _| { 
712-                                     // We don't want to name the arguments, we just want to give an 
713-                                     // idea of what the syntax is. 
714-                                     match  param. kind  { 
715-                                         ty:: GenericParamDefKind :: Lifetime  => { 
716-                                             self . infcx . tcx . lifetimes . re_erased . into ( ) 
717-                                         } 
718-                                         ty:: GenericParamDefKind :: Type  {  .. }  => { 
719-                                             self . next_ty_var ( DUMMY_SP ) . into ( ) 
720-                                         } 
721-                                         ty:: GenericParamDefKind :: Const  {  .. }  => { 
722-                                             self . next_const_var ( DUMMY_SP ) . into ( ) 
723-                                         } 
724-                                     } 
725-                                 } , 
726-                             ) ; 
727-                             let  impl_trait_ref = self 
728-                                 . infcx 
729-                                 . tcx 
730-                                 . impl_trait_ref ( impl_def_id) 
731-                                 . unwrap ( ) 
732-                                 . instantiate ( self . infcx . tcx ,  impl_args) ; 
733-                             let  impl_self_ty = impl_trait_ref. self_ty ( ) ; 
734-                             if  self . infcx . can_eq ( param_env,  impl_self_ty,  args. type_at ( 0 ) )  { 
735-                                 // The expr's self type could conform to this impl's self type. 
736-                             }  else  { 
737-                                 // Nope, don't bother. 
738-                                 return ; 
739-                             } 
740-                             let  assocs = self . infcx . tcx . associated_items ( impl_def_id) ; 
741- 
742-                             if  self 
743-                                 . infcx 
744-                                 . tcx 
745-                                 . is_diagnostic_item ( sym:: blanket_into_impl,  impl_def_id) 
746-                                 && let  Some ( did)  = self . infcx . tcx . get_diagnostic_item ( sym:: From ) 
747-                             { 
748-                                 let  mut  found = false ; 
749-                                 self . infcx . tcx . for_each_impl ( did,  |impl_def_id| { 
750-                                     // We had an `<A as Into<B>::into` and we've hit the blanket 
751-                                     // impl for `From<A>`. So we try and look for the right `From` 
752-                                     // impls that *would* apply. We *could* do this in a generalized 
753-                                     // version by evaluating the `where` clauses, but that would be 
754-                                     // way too involved to implement. Instead we special case the 
755-                                     // arguably most common case of `expr.into()`. 
756-                                     let  Some ( header)  =
757-                                         self . infcx . tcx . impl_trait_header ( impl_def_id) 
758-                                     else  { 
759-                                         return ; 
760-                                     } ; 
761-                                     let  target = header. trait_ref . skip_binder ( ) . args . type_at ( 0 ) ; 
762-                                     let  ty = header. trait_ref . skip_binder ( ) . args . type_at ( 1 ) ; 
763-                                     if  ty == args. type_at ( 0 )  { 
764-                                         paths. push ( format ! ( "<{ty} as Into<{target}>>::into" ) ) ; 
765-                                         found = true ; 
766-                                     } 
767-                                 } ) ; 
768-                                 if  found { 
769-                                     return ; 
770-                                 } 
771-                             } 
772- 
773-                             // We're at the `impl` level, but we want to get the same method we 
774-                             // called *on this `impl`*, in order to get the right DefId and args. 
775-                             let  Some ( assoc)  = assocs. filter_by_name_unhygienic ( name) . next ( )  else  { 
776-                                 // The method isn't in this `impl`? Not useful to us then. 
777-                                 return ; 
778-                             } ; 
779-                             let  Some ( trait_assoc_item)  = assoc. trait_item_def_id  else  { 
780-                                 return ; 
781-                             } ; 
782-                             let  trait_assoc_substs = impl_trait_ref. args . extend_to ( 
783-                                 self . infcx . tcx , 
784-                                 trait_assoc_item, 
785-                                 |def,  _| { 
786-                                     // We don't want to name the arguments, we just want to give an 
787-                                     // idea of what the syntax is. 
788-                                     match  def. kind  { 
789-                                         ty:: GenericParamDefKind :: Lifetime  => { 
790-                                             self . infcx . tcx . lifetimes . re_erased . into ( ) 
791-                                         } 
792-                                         ty:: GenericParamDefKind :: Type  {  .. }  => { 
793-                                             self . next_ty_var ( DUMMY_SP ) . into ( ) 
794-                                         } 
795-                                         ty:: GenericParamDefKind :: Const  {  .. }  => { 
796-                                             self . next_const_var ( DUMMY_SP ) . into ( ) 
797-                                         } 
798-                                     } 
799-                                 } , 
800-                             ) ; 
801-                             let  identity_method =
802-                                 args. rebase_onto ( self . infcx . tcx ,  def_id,  trait_assoc_substs) ; 
803-                             let  mut  printer = fmt_printer ( self ,  Namespace :: ValueNS ) ; 
804-                             printer. print_def_path ( def_id,  identity_method) . unwrap ( ) ; 
805-                             paths. push ( printer. into_buffer ( ) ) ; 
806-                         } , 
807-                     ) ; 
590+                     let  paths =
591+                         self . get_suggestions ( args. type_at ( 0 ) ,  def_id,  false ,  param_env,  Some ( args) ) ; 
808592                    if  paths. len ( )  > 20  || paths. is_empty ( )  { 
809593                        // This will show the fallback impl, so the expression will have type 
810594                        // parameter placeholders, but it's better than nothing. 
@@ -875,6 +659,113 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
875659            } ) , 
876660        } 
877661    } 
662+ 
663+     fn  get_suggestions ( 
664+         & self , 
665+         ty :  Ty < ' tcx > ,  // args.type_at(0) / ty 
666+         def_id :  DefId , 
667+         target_type :  bool ,  // false / true 
668+         param_env :  ty:: ParamEnv < ' tcx > , 
669+         args :  Option < & ty:: GenericArgs < ' tcx > > , 
670+     )  -> Vec < String >  { 
671+         let  tcx = self . infcx . tcx ; 
672+         let  mut  paths = vec ! [ ] ; 
673+         let  name = tcx. item_name ( def_id) ; 
674+         let  empty_args = |def_id| { 
675+             ty:: GenericArgs :: for_item ( tcx,  def_id,  |param,  _| { 
676+                 // We don't want to name the arguments, we just want to give an 
677+                 // idea of what the syntax is. 
678+                 match  param. kind  { 
679+                     ty:: GenericParamDefKind :: Lifetime  => tcx. lifetimes . re_erased . into ( ) , 
680+                     ty:: GenericParamDefKind :: Type  {  .. }  => self . next_ty_var ( DUMMY_SP ) . into ( ) , 
681+                     ty:: GenericParamDefKind :: Const  {  .. }  => self . next_const_var ( DUMMY_SP ) . into ( ) , 
682+                 } 
683+             } ) 
684+         } ; 
685+         let  args = args. unwrap_or_else ( || empty_args ( def_id) ) ; 
686+         tcx. for_each_relevant_impl ( 
687+             tcx. parent ( def_id) ,  // Trait `DefId` 
688+             ty,                  // `Self` type 
689+             |impl_def_id| { 
690+                 let  impl_args = empty_args ( impl_def_id) ; 
691+                 let  impl_trait_ref =
692+                     tcx. impl_trait_ref ( impl_def_id) . unwrap ( ) . instantiate ( tcx,  impl_args) ; 
693+                 let  impl_self_ty = impl_trait_ref. self_ty ( ) ; 
694+                 if  self . infcx . can_eq ( param_env,  impl_self_ty,  ty)  { 
695+                     // The expr's self type could conform to this impl's self type. 
696+                 }  else  { 
697+                     // Nope, don't bother. 
698+                     return ; 
699+                 } 
700+                 let  assocs = tcx. associated_items ( impl_def_id) ; 
701+ 
702+                 if  tcx. is_diagnostic_item ( sym:: blanket_into_impl,  impl_def_id) 
703+                     && let  Some ( did)  = tcx. get_diagnostic_item ( sym:: From ) 
704+                 { 
705+                     let  mut  found = false ; 
706+                     tcx. for_each_impl ( did,  |impl_def_id| { 
707+                         // We had an `<A as Into<B>::into` and we've hit the blanket 
708+                         // impl for `From<A>`. So we try and look for the right `From` 
709+                         // impls that *would* apply. We *could* do this in a generalized 
710+                         // version by evaluating the `where` clauses, but that would be 
711+                         // way too involved to implement. Instead we special case the 
712+                         // arguably most common case of `expr.into()`. 
713+                         let  Some ( header)  = tcx. impl_trait_header ( impl_def_id)  else  { 
714+                             return ; 
715+                         } ; 
716+                         let  target = header. trait_ref . skip_binder ( ) . args . type_at ( 0 ) ; 
717+                         let  _ty = header. trait_ref . skip_binder ( ) . args . type_at ( 1 ) ; 
718+                         if  _ty == ty { 
719+                             if  target_type { 
720+                                 paths. push ( format ! ( "{target}" ) ) ; 
721+                             }  else  { 
722+                                 paths. push ( format ! ( "<{ty} as Into<{target}>>::into" ) ) ; 
723+                             } 
724+                             found = true ; 
725+                         } 
726+                     } ) ; 
727+                     if  found { 
728+                         return ; 
729+                     } 
730+                 } 
731+ 
732+                 // We're at the `impl` level, but we want to get the same method we 
733+                 // called *on this `impl`*, in order to get the right DefId and args. 
734+                 let  Some ( assoc)  = assocs. filter_by_name_unhygienic ( name) . next ( )  else  { 
735+                     // The method isn't in this `impl`? Not useful to us then. 
736+                     return ; 
737+                 } ; 
738+                 let  Some ( trait_assoc_item)  = assoc. trait_item_def_id  else  { 
739+                     return ; 
740+                 } ; 
741+                 let  trait_assoc_substs =
742+                     impl_trait_ref. args . extend_to ( tcx,  trait_assoc_item,  |def,  _| { 
743+                         // We don't want to name the arguments, we just want to give an 
744+                         // idea of what the syntax is. 
745+                         match  def. kind  { 
746+                             ty:: GenericParamDefKind :: Lifetime  => tcx. lifetimes . re_erased . into ( ) , 
747+                             ty:: GenericParamDefKind :: Type  {  .. }  => { 
748+                                 self . next_ty_var ( DUMMY_SP ) . into ( ) 
749+                             } 
750+                             ty:: GenericParamDefKind :: Const  {  .. }  => { 
751+                                 self . next_const_var ( DUMMY_SP ) . into ( ) 
752+                             } 
753+                         } 
754+                     } ) ; 
755+                 let  identity_method = args. rebase_onto ( tcx,  def_id,  trait_assoc_substs) ; 
756+                 if  target_type { 
757+                     let  fn_sig = tcx. fn_sig ( def_id) . instantiate ( tcx,  identity_method) ; 
758+                     let  ret = fn_sig. skip_binder ( ) . output ( ) ; 
759+                     paths. push ( format ! ( "{ret}" ) ) ; 
760+                 }  else  { 
761+                     let  mut  printer = fmt_printer ( self ,  Namespace :: ValueNS ) ; 
762+                     printer. print_def_path ( def_id,  identity_method) . unwrap ( ) ; 
763+                     paths. push ( printer. into_buffer ( ) ) ; 
764+                 } 
765+             } , 
766+         ) ; 
767+         paths
768+     } 
878769} 
879770
880771#[ derive( Debug ) ]  
0 commit comments