@@ -315,8 +315,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
315
315
body_id : Option < hir:: BodyId > ,
316
316
failure_span : Span ,
317
317
arg : GenericArg < ' tcx > ,
318
- // FIXME(#94483): Either use this or remove it.
319
- _impl_candidates : Vec < ty:: TraitRef < ' tcx > > ,
320
318
error_code : TypeAnnotationNeeded ,
321
319
should_label_span : bool ,
322
320
) -> DiagnosticBuilder < ' tcx , ErrorGuaranteed > {
@@ -534,6 +532,23 @@ enum InferSourceKind<'tcx> {
534
532
} ,
535
533
}
536
534
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
+
537
552
impl < ' tcx > InferSourceKind < ' tcx > {
538
553
fn ty_msg ( & self , infcx : & InferCtxt < ' _ , ' tcx > ) -> String {
539
554
match * self {
@@ -604,57 +619,85 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
604
619
/// Sources with a small cost are prefer and should result
605
620
/// in a clearer and idiomatic suggestion.
606
621
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 > ,
615
625
}
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
+ }
623
653
}
624
654
}
625
655
626
656
// 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) ,
630
662
InferSourceKind :: GenericArg { def_id, generic_args, .. } => {
631
663
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 ,
634
667
} ;
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 > ( )
636
669
}
637
670
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 > ( )
639
672
}
640
673
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 }
642
675
}
643
- }
676
+ } ;
677
+
678
+ let suggestion_may_apply = if source. from_expansion ( ) { 10000 } else { 0 } ;
679
+
680
+ base_cost + suggestion_may_apply
644
681
}
645
682
646
683
/// Uses `fn source_cost` to determine whether this inference source is preferable to
647
684
/// previous sources. We generally prefer earlier sources.
648
685
#[ instrument( level = "debug" , skip( self ) ) ]
649
686
fn update_infer_source ( & mut self , new_source : InferSource < ' tcx > ) {
650
687
let cost = self . source_cost ( & new_source) + self . attempt ;
688
+ debug ! ( ?cost) ;
651
689
self . attempt += 1 ;
652
690
if cost < self . infer_source_cost {
653
691
self . infer_source_cost = cost;
654
692
self . infer_source = Some ( new_source) ;
655
693
}
656
694
}
657
695
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
+
658
701
fn opt_node_type ( & self , hir_id : HirId ) -> Option < Ty < ' tcx > > {
659
702
let ty = self . typeck_results . node_type_opt ( hir_id) ;
660
703
self . infcx . resolve_vars_if_possible ( ty)
@@ -737,7 +780,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
737
780
let tcx = self . infcx . tcx ;
738
781
match expr. kind {
739
782
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 ) {
741
784
return self . path_inferred_subst_iter ( expr. hir_id , substs, path) ;
742
785
}
743
786
}
@@ -765,7 +808,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
765
808
if generics. has_impl_trait ( ) {
766
809
None ?
767
810
}
768
- let substs = self . typeck_results . node_substs_opt ( expr. hir_id ) ?;
811
+ let substs = self . node_substs_opt ( expr. hir_id ) ?;
769
812
let span = tcx. hir ( ) . span ( segment. hir_id ?) ;
770
813
let insert_span = segment. ident . span . shrink_to_hi ( ) . with_hi ( span. hi ( ) ) ;
771
814
InsertableGenericArgs {
@@ -980,8 +1023,10 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
980
1023
debug ! ( ?args) ;
981
1024
let InsertableGenericArgs { insert_span, substs, generics_def_id, def_id } = args;
982
1025
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) )
985
1030
{
986
1031
let substs = self . infcx . resolve_vars_if_possible ( substs) ;
987
1032
let generic_args = & generics. own_substs_no_defaults ( tcx, substs)
@@ -1037,7 +1082,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
1037
1082
. any ( |generics| generics. has_impl_trait ( ) )
1038
1083
} ;
1039
1084
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 )
1041
1086
&& substs. iter ( ) . any ( |arg| self . generic_arg_contains_target ( arg) )
1042
1087
&& let Some ( def_id) = self . typeck_results . type_dependent_def_id ( expr. hir_id )
1043
1088
&& self . infcx . tcx . trait_of_item ( def_id) . is_some ( )
0 commit comments