@@ -315,8 +315,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
315315 body_id : Option < hir:: BodyId > ,
316316 failure_span : Span ,
317317 arg : GenericArg < ' tcx > ,
318- // FIXME(#94483): Either use this or remove it.
319- _impl_candidates : Vec < ty:: TraitRef < ' tcx > > ,
320318 error_code : TypeAnnotationNeeded ,
321319 should_label_span : bool ,
322320 ) -> DiagnosticBuilder < ' tcx , ErrorGuaranteed > {
@@ -534,6 +532,23 @@ enum InferSourceKind<'tcx> {
534532 } ,
535533}
536534
535+ impl < ' tcx > InferSource < ' tcx > {
536+ fn from_expansion ( & self ) -> bool {
537+ let source_from_expansion = match self . kind {
538+ InferSourceKind :: LetBinding { insert_span, .. }
539+ | InferSourceKind :: ClosureArg { insert_span, .. }
540+ | InferSourceKind :: GenericArg { insert_span, .. } => insert_span. from_expansion ( ) ,
541+ InferSourceKind :: FullyQualifiedMethodCall { receiver, .. } => {
542+ receiver. span . from_expansion ( )
543+ }
544+ InferSourceKind :: ClosureReturn { data, should_wrap_expr, .. } => {
545+ data. span ( ) . from_expansion ( ) || should_wrap_expr. map_or ( false , Span :: from_expansion)
546+ }
547+ } ;
548+ source_from_expansion || self . span . from_expansion ( )
549+ }
550+ }
551+
537552impl < ' tcx > InferSourceKind < ' tcx > {
538553 fn ty_msg ( & self , infcx : & InferCtxt < ' _ , ' tcx > ) -> String {
539554 match * self {
@@ -604,57 +619,85 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
604619 /// Sources with a small cost are prefer and should result
605620 /// in a clearer and idiomatic suggestion.
606621 fn source_cost ( & self , source : & InferSource < ' tcx > ) -> usize {
607- let tcx = self . infcx . tcx ;
608-
609- fn arg_cost < ' tcx > ( arg : GenericArg < ' tcx > ) -> usize {
610- match arg. unpack ( ) {
611- GenericArgKind :: Lifetime ( _) => 0 , // erased
612- GenericArgKind :: Type ( ty) => ty_cost ( ty) ,
613- GenericArgKind :: Const ( _) => 3 , // some non-zero value
614- }
622+ #[ derive( Clone , Copy ) ]
623+ struct CostCtxt < ' tcx > {
624+ tcx : TyCtxt < ' tcx > ,
615625 }
616- fn ty_cost < ' tcx > ( ty : Ty < ' tcx > ) -> usize {
617- match ty. kind ( ) {
618- ty:: Closure ( ..) => 100 ,
619- ty:: FnDef ( ..) => 20 ,
620- ty:: FnPtr ( ..) => 10 ,
621- ty:: Infer ( ..) => 0 ,
622- _ => 1 ,
626+ impl < ' tcx > CostCtxt < ' tcx > {
627+ fn arg_cost ( self , arg : GenericArg < ' tcx > ) -> usize {
628+ match arg. unpack ( ) {
629+ GenericArgKind :: Lifetime ( _) => 0 , // erased
630+ GenericArgKind :: Type ( ty) => self . ty_cost ( ty) ,
631+ GenericArgKind :: Const ( _) => 3 , // some non-zero value
632+ }
633+ }
634+ fn ty_cost ( self , ty : Ty < ' tcx > ) -> usize {
635+ match * ty. kind ( ) {
636+ ty:: Closure ( ..) => 1000 ,
637+ ty:: FnDef ( ..) => 150 ,
638+ ty:: FnPtr ( ..) => 30 ,
639+ ty:: Adt ( def, substs) => {
640+ 5 + self
641+ . tcx
642+ . generics_of ( def. did ( ) )
643+ . own_substs_no_defaults ( self . tcx , substs)
644+ . iter ( )
645+ . map ( |& arg| self . arg_cost ( arg) )
646+ . sum :: < usize > ( )
647+ }
648+ ty:: Tuple ( args) => 5 + args. iter ( ) . map ( |arg| self . ty_cost ( arg) ) . sum :: < usize > ( ) ,
649+ ty:: Ref ( _, ty, _) => 2 + self . ty_cost ( ty) ,
650+ ty:: Infer ( ..) => 0 ,
651+ _ => 1 ,
652+ }
623653 }
624654 }
625655
626656 // The sources are listed in order of preference here.
627- match source. kind {
628- InferSourceKind :: LetBinding { ty, .. } => ty_cost ( ty) ,
629- InferSourceKind :: ClosureArg { ty, .. } => 5 + ty_cost ( ty) ,
657+ let tcx = self . infcx . tcx ;
658+ let ctx = CostCtxt { tcx } ;
659+ let base_cost = match source. kind {
660+ InferSourceKind :: LetBinding { ty, .. } => ctx. ty_cost ( ty) ,
661+ InferSourceKind :: ClosureArg { ty, .. } => ctx. ty_cost ( ty) ,
630662 InferSourceKind :: GenericArg { def_id, generic_args, .. } => {
631663 let variant_cost = match tcx. def_kind ( def_id) {
632- DefKind :: Variant | DefKind :: Ctor ( CtorOf :: Variant , _) => 15 , // `None::<u32>` and friends are ugly.
633- _ => 12 ,
664+ // `None::<u32>` and friends are ugly.
665+ DefKind :: Variant | DefKind :: Ctor ( CtorOf :: Variant , _) => 15 ,
666+ _ => 10 ,
634667 } ;
635- variant_cost + generic_args. iter ( ) . map ( |& arg| arg_cost ( arg) ) . sum :: < usize > ( )
668+ variant_cost + generic_args. iter ( ) . map ( |& arg| ctx . arg_cost ( arg) ) . sum :: < usize > ( )
636669 }
637670 InferSourceKind :: FullyQualifiedMethodCall { substs, .. } => {
638- 20 + substs. iter ( ) . map ( |arg| arg_cost ( arg) ) . sum :: < usize > ( )
671+ 20 + substs. iter ( ) . map ( |arg| ctx . arg_cost ( arg) ) . sum :: < usize > ( )
639672 }
640673 InferSourceKind :: ClosureReturn { ty, should_wrap_expr, .. } => {
641- 30 + ty_cost ( ty) + if should_wrap_expr. is_some ( ) { 10 } else { 0 }
674+ 30 + ctx . ty_cost ( ty) + if should_wrap_expr. is_some ( ) { 10 } else { 0 }
642675 }
643- }
676+ } ;
677+
678+ let suggestion_may_apply = if source. from_expansion ( ) { 10000 } else { 0 } ;
679+
680+ base_cost + suggestion_may_apply
644681 }
645682
646683 /// Uses `fn source_cost` to determine whether this inference source is preferable to
647684 /// previous sources. We generally prefer earlier sources.
648685 #[ instrument( level = "debug" , skip( self ) ) ]
649686 fn update_infer_source ( & mut self , new_source : InferSource < ' tcx > ) {
650687 let cost = self . source_cost ( & new_source) + self . attempt ;
688+ debug ! ( ?cost) ;
651689 self . attempt += 1 ;
652690 if cost < self . infer_source_cost {
653691 self . infer_source_cost = cost;
654692 self . infer_source = Some ( new_source) ;
655693 }
656694 }
657695
696+ fn node_substs_opt ( & self , hir_id : HirId ) -> Option < SubstsRef < ' tcx > > {
697+ let substs = self . typeck_results . node_substs_opt ( hir_id) ;
698+ self . infcx . resolve_vars_if_possible ( substs)
699+ }
700+
658701 fn opt_node_type ( & self , hir_id : HirId ) -> Option < Ty < ' tcx > > {
659702 let ty = self . typeck_results . node_type_opt ( hir_id) ;
660703 self . infcx . resolve_vars_if_possible ( ty)
@@ -737,7 +780,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
737780 let tcx = self . infcx . tcx ;
738781 match expr. kind {
739782 hir:: ExprKind :: Path ( ref path) => {
740- if let Some ( substs) = self . typeck_results . node_substs_opt ( expr. hir_id ) {
783+ if let Some ( substs) = self . node_substs_opt ( expr. hir_id ) {
741784 return self . path_inferred_subst_iter ( expr. hir_id , substs, path) ;
742785 }
743786 }
@@ -765,7 +808,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
765808 if generics. has_impl_trait ( ) {
766809 None ?
767810 }
768- let substs = self . typeck_results . node_substs_opt ( expr. hir_id ) ?;
811+ let substs = self . node_substs_opt ( expr. hir_id ) ?;
769812 let span = tcx. hir ( ) . span ( segment. hir_id ?) ;
770813 let insert_span = segment. ident . span . shrink_to_hi ( ) . with_hi ( span. hi ( ) ) ;
771814 InsertableGenericArgs {
@@ -980,8 +1023,10 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
9801023 debug ! ( ?args) ;
9811024 let InsertableGenericArgs { insert_span, substs, generics_def_id, def_id } = args;
9821025 let generics = tcx. generics_of ( generics_def_id) ;
983- if let Some ( argument_index) =
984- generics. own_substs ( substs) . iter ( ) . position ( |& arg| self . generic_arg_is_target ( arg) )
1026+ if let Some ( argument_index) = generics
1027+ . own_substs ( substs)
1028+ . iter ( )
1029+ . position ( |& arg| self . generic_arg_contains_target ( arg) )
9851030 {
9861031 let substs = self . infcx . resolve_vars_if_possible ( substs) ;
9871032 let generic_args = & generics. own_substs_no_defaults ( tcx, substs)
@@ -1037,7 +1082,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
10371082 . any ( |generics| generics. has_impl_trait ( ) )
10381083 } ;
10391084 if let ExprKind :: MethodCall ( path, args, span) = expr. kind
1040- && let Some ( substs) = self . typeck_results . node_substs_opt ( expr. hir_id )
1085+ && let Some ( substs) = self . node_substs_opt ( expr. hir_id )
10411086 && substs. iter ( ) . any ( |arg| self . generic_arg_contains_target ( arg) )
10421087 && let Some ( def_id) = self . typeck_results . type_dependent_def_id ( expr. hir_id )
10431088 && self . infcx . tcx . trait_of_item ( def_id) . is_some ( )
0 commit comments