@@ -602,41 +602,58 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
602602 /// Sources with a small cost are prefer and should result
603603 /// in a clearer and idiomatic suggestion.
604604 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 > ,
613608 }
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+ }
621635 }
622636 }
623637
624638 // The sources are listed in order of preference here.
639+ let tcx = self . infcx . tcx ;
640+ let ctx = CostCtxt { tcx } ;
625641 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) ,
628644 InferSourceKind :: GenericArg { def_id, generic_args, .. } => {
629645 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 ,
632649 } ;
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 > ( )
634651 }
635652 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 > ( )
637654 }
638655 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 }
640657 }
641658 }
642659 }
@@ -646,6 +663,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
646663 #[ instrument( level = "debug" , skip( self ) ) ]
647664 fn update_infer_source ( & mut self , new_source : InferSource < ' tcx > ) {
648665 let cost = self . source_cost ( & new_source) + self . attempt ;
666+ debug ! ( ?cost) ;
649667 self . attempt += 1 ;
650668 if cost < self . infer_source_cost {
651669 self . infer_source_cost = cost;
0 commit comments