@@ -602,41 +602,58 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
602
602
/// Sources with a small cost are prefer and should result
603
603
/// in a clearer and idiomatic suggestion.
604
604
fn source_cost ( & self , source : & InferSource < ' tcx > ) -> usize {
605
- let tcx = self . infcx . tcx ;
606
-
607
- fn arg_cost < ' tcx > ( arg : GenericArg < ' tcx > ) -> usize {
608
- match arg. unpack ( ) {
609
- GenericArgKind :: Lifetime ( _) => 0 , // erased
610
- GenericArgKind :: Type ( ty) => ty_cost ( ty) ,
611
- GenericArgKind :: Const ( _) => 3 , // some non-zero value
612
- }
605
+ #[ derive( Clone , Copy ) ]
606
+ struct CostCtxt < ' tcx > {
607
+ tcx : TyCtxt < ' tcx > ,
613
608
}
614
- fn ty_cost < ' tcx > ( ty : Ty < ' tcx > ) -> usize {
615
- match ty. kind ( ) {
616
- ty:: Closure ( ..) => 100 ,
617
- ty:: FnDef ( ..) => 20 ,
618
- ty:: FnPtr ( ..) => 10 ,
619
- ty:: Infer ( ..) => 0 ,
620
- _ => 1 ,
609
+ impl < ' tcx > CostCtxt < ' tcx > {
610
+ fn arg_cost ( self , arg : GenericArg < ' tcx > ) -> usize {
611
+ match arg. unpack ( ) {
612
+ GenericArgKind :: Lifetime ( _) => 0 , // erased
613
+ GenericArgKind :: Type ( ty) => self . ty_cost ( ty) ,
614
+ GenericArgKind :: Const ( _) => 3 , // some non-zero value
615
+ }
616
+ }
617
+ fn ty_cost ( self , ty : Ty < ' tcx > ) -> usize {
618
+ match ty. kind ( ) {
619
+ ty:: Closure ( ..) => 1000 ,
620
+ ty:: FnDef ( ..) => 150 ,
621
+ ty:: FnPtr ( ..) => 30 ,
622
+ ty:: Adt ( def, substs) => {
623
+ 5 + self
624
+ . tcx
625
+ . generics_of ( def. did ( ) )
626
+ . own_substs_no_defaults ( self . tcx , substs)
627
+ . iter ( )
628
+ . map ( |& arg| self . arg_cost ( arg) )
629
+ . sum :: < usize > ( )
630
+ }
631
+ ty:: Tuple ( args) => 5 + args. iter ( ) . map ( |arg| self . ty_cost ( arg) ) . sum :: < usize > ( ) ,
632
+ ty:: Infer ( ..) => 0 ,
633
+ _ => 1 ,
634
+ }
621
635
}
622
636
}
623
637
624
638
// The sources are listed in order of preference here.
639
+ let tcx = self . infcx . tcx ;
640
+ let ctx = CostCtxt { tcx } ;
625
641
match source. kind {
626
- InferSourceKind :: LetBinding { ty, .. } => ty_cost ( ty) ,
627
- InferSourceKind :: ClosureArg { ty, .. } => 5 + ty_cost ( ty) ,
642
+ InferSourceKind :: LetBinding { ty, .. } => ctx . ty_cost ( ty) ,
643
+ InferSourceKind :: ClosureArg { ty, .. } => ctx . ty_cost ( ty) ,
628
644
InferSourceKind :: GenericArg { def_id, generic_args, .. } => {
629
645
let variant_cost = match tcx. def_kind ( def_id) {
630
- DefKind :: Variant | DefKind :: Ctor ( CtorOf :: Variant , _) => 15 , // `None::<u32>` and friends are ugly.
631
- _ => 12 ,
646
+ // `None::<u32>` and friends are ugly.
647
+ DefKind :: Variant | DefKind :: Ctor ( CtorOf :: Variant , _) => 15 ,
648
+ _ => 10 ,
632
649
} ;
633
- variant_cost + generic_args. iter ( ) . map ( |& arg| arg_cost ( arg) ) . sum :: < usize > ( )
650
+ variant_cost + generic_args. iter ( ) . map ( |& arg| ctx . arg_cost ( arg) ) . sum :: < usize > ( )
634
651
}
635
652
InferSourceKind :: FullyQualifiedMethodCall { substs, .. } => {
636
- 20 + substs. iter ( ) . map ( |arg| arg_cost ( arg) ) . sum :: < usize > ( )
653
+ 20 + substs. iter ( ) . map ( |arg| ctx . arg_cost ( arg) ) . sum :: < usize > ( )
637
654
}
638
655
InferSourceKind :: ClosureReturn { ty, should_wrap_expr, .. } => {
639
- 30 + ty_cost ( ty) + if should_wrap_expr. is_some ( ) { 10 } else { 0 }
656
+ 30 + ctx . ty_cost ( ty) + if should_wrap_expr. is_some ( ) { 10 } else { 0 }
640
657
}
641
658
}
642
659
}
@@ -646,6 +663,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
646
663
#[ instrument( level = "debug" , skip( self ) ) ]
647
664
fn update_infer_source ( & mut self , new_source : InferSource < ' tcx > ) {
648
665
let cost = self . source_cost ( & new_source) + self . attempt ;
666
+ debug ! ( ?cost) ;
649
667
self . attempt += 1 ;
650
668
if cost < self . infer_source_cost {
651
669
self . infer_source_cost = cost;
0 commit comments