@@ -453,15 +453,23 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
453
453
let mut infer_subdiags = Vec :: new ( ) ;
454
454
let mut multi_suggestions = Vec :: new ( ) ;
455
455
match kind {
456
- InferSourceKind :: LetBinding { insert_span, pattern_name, ty, def_id, hir_id } => {
456
+ InferSourceKind :: LetBinding {
457
+ insert_span,
458
+ pattern_name,
459
+ ty,
460
+ def_id,
461
+ init_expr_hir_id,
462
+ } => {
457
463
let mut paths = vec ! [ ] ;
458
464
if let Some ( def_id) = def_id
459
- && let Some ( hir_id) = hir_id
465
+ && let Some ( hir_id) = init_expr_hir_id
460
466
&& let expr = self . infcx . tcx . hir ( ) . expect_expr ( hir_id)
461
467
&& let hir:: ExprKind :: MethodCall ( _, rcvr, _, _) = expr. kind
462
468
&& let Some ( ty) = typeck_results. node_type_opt ( rcvr. hir_id )
463
469
{
464
- paths = self . get_suggestions ( ty, def_id, true , param_env, None , predicate) ;
470
+ paths = self . get_fully_qualified_path_suggestions_from_impls (
471
+ ty, def_id, true , param_env, predicate,
472
+ ) ;
465
473
}
466
474
467
475
if paths. is_empty ( ) {
@@ -588,12 +596,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
588
596
589
597
// Look for all the possible implementations to suggest, otherwise we'll show
590
598
// just suggest the syntax for the fully qualified path with placeholders.
591
- let paths = self . get_suggestions (
599
+ let paths = self . get_fully_qualified_path_suggestions_from_impls (
592
600
args. type_at ( 0 ) ,
593
601
def_id,
594
602
false ,
595
603
param_env,
596
- Some ( args) ,
597
604
predicate,
598
605
) ;
599
606
if paths. len ( ) > 20 || paths. is_empty ( ) {
@@ -667,33 +674,21 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
667
674
}
668
675
}
669
676
670
- fn get_suggestions (
677
+ fn get_fully_qualified_path_suggestions_from_impls (
671
678
& self ,
672
679
self_ty : Ty < ' tcx > ,
673
680
def_id : DefId ,
674
681
target_type : bool ,
675
682
param_env : ty:: ParamEnv < ' tcx > ,
676
- args : Option < & ty:: GenericArgs < ' tcx > > ,
677
683
predicate : Option < ty:: Predicate < ' tcx > > ,
678
684
) -> Vec < String > {
679
685
let tcx = self . infcx . tcx ;
680
686
let mut paths = vec ! [ ] ;
681
687
let name = tcx. item_name ( def_id) ;
682
- let empty_args = |def_id| {
683
- ty:: GenericArgs :: for_item ( tcx, def_id, |param, _| {
684
- // We don't want to name the arguments, we just want to give an
685
- // idea of what the syntax is.
686
- match param. kind {
687
- ty:: GenericParamDefKind :: Lifetime => tcx. lifetimes . re_erased . into ( ) ,
688
- ty:: GenericParamDefKind :: Type { .. } => self . next_ty_var ( DUMMY_SP ) . into ( ) ,
689
- ty:: GenericParamDefKind :: Const { .. } => self . next_const_var ( DUMMY_SP ) . into ( ) ,
690
- }
691
- } )
692
- } ;
693
- let args = args. unwrap_or_else ( || empty_args ( def_id) ) ;
688
+ let args = self . fresh_args_for_item ( DUMMY_SP , def_id) ;
694
689
let trait_def_id = tcx. parent ( def_id) ;
695
690
tcx. for_each_relevant_impl ( trait_def_id, self_ty, |impl_def_id| {
696
- let impl_args = empty_args ( impl_def_id) ;
691
+ let impl_args = self . fresh_args_for_item ( DUMMY_SP , impl_def_id) ;
697
692
let impl_trait_ref =
698
693
tcx. impl_trait_ref ( impl_def_id) . unwrap ( ) . instantiate ( tcx, impl_args) ;
699
694
let impl_self_ty = impl_trait_ref. self_ty ( ) ;
@@ -704,18 +699,28 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
704
699
return ;
705
700
}
706
701
702
+ let lang = tcx. lang_items ( ) ;
707
703
let filter = if let Some ( ty:: ProjectionPredicate {
708
704
projection_term : ty:: AliasTerm { def_id, .. } ,
709
705
term,
710
706
} ) =
711
707
predicate. and_then ( |p| p. as_projection_clause ( ) ) . map ( |p| p. skip_binder ( ) )
712
708
&& let ty:: TermKind :: Ty ( assoc_ty) = term. unpack ( )
713
709
&& tcx. item_name ( def_id) == sym:: Output
710
+ && [
711
+ lang. add_trait ( ) ,
712
+ lang. sub_trait ( ) ,
713
+ lang. mul_trait ( ) ,
714
+ lang. div_trait ( ) ,
715
+ lang. rem_trait ( ) ,
716
+ lang. neg_trait ( ) ,
717
+ ]
718
+ . contains ( & Some ( tcx. parent ( def_id) ) )
714
719
{
715
720
// If the predicate that failed to be inferred is an associated type called
716
- // "Output" (presumably from one of the math traits), we will only mention the
717
- // `Into` and ` From` impls that correspond to the self type as well, so as to
718
- // avoid showing multiple conversion options.
721
+ // "Output" (from one of the math traits), we will only mention the `Into` and
722
+ // `From` impls that correspond to the self type as well, so as to avoid showing
723
+ // multiple conversion options.
719
724
Some ( assoc_ty)
720
725
} else {
721
726
None
@@ -766,26 +771,16 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
766
771
return ;
767
772
} ;
768
773
let trait_assoc_substs =
769
- impl_trait_ref. args . extend_to ( tcx, trait_assoc_item, |def, _| {
770
- // We don't want to name the arguments, we just want to give an
771
- // idea of what the syntax is.
772
- match def. kind {
773
- ty:: GenericParamDefKind :: Lifetime => tcx. lifetimes . re_erased . into ( ) ,
774
- ty:: GenericParamDefKind :: Type { .. } => self . next_ty_var ( DUMMY_SP ) . into ( ) ,
775
- ty:: GenericParamDefKind :: Const { .. } => {
776
- self . next_const_var ( DUMMY_SP ) . into ( )
777
- }
778
- }
779
- } ) ;
774
+ impl_trait_ref
775
+ . args
776
+ . extend_to ( tcx, trait_assoc_item, |def, _| self . var_for_def ( DUMMY_SP , def) ) ;
780
777
let identity_method = args. rebase_onto ( tcx, def_id, trait_assoc_substs) ;
781
778
if target_type {
782
779
let fn_sig = tcx. fn_sig ( def_id) . instantiate ( tcx, identity_method) ;
783
780
let ret = fn_sig. skip_binder ( ) . output ( ) ;
784
781
paths. push ( format ! ( "{ret}" ) ) ;
785
782
} else {
786
- let mut printer = fmt_printer ( self , Namespace :: ValueNS ) ;
787
- printer. print_def_path ( def_id, identity_method) . unwrap ( ) ;
788
- paths. push ( printer. into_buffer ( ) ) ;
783
+ paths. push ( self . tcx . value_path_str_with_args ( def_id, identity_method) ) ;
789
784
}
790
785
} ) ;
791
786
paths
@@ -805,7 +800,7 @@ enum InferSourceKind<'tcx> {
805
800
pattern_name : Option < Ident > ,
806
801
ty : Ty < ' tcx > ,
807
802
def_id : Option < DefId > ,
808
- hir_id : Option < HirId > ,
803
+ init_expr_hir_id : Option < HirId > ,
809
804
} ,
810
805
ClosureArg {
811
806
insert_span : Span ,
@@ -1304,7 +1299,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
1304
1299
pattern_name : local. pat . simple_ident ( ) ,
1305
1300
ty,
1306
1301
def_id : None ,
1307
- hir_id : local. init . map ( |e| e. hir_id ) ,
1302
+ init_expr_hir_id : local. init . map ( |e| e. hir_id ) ,
1308
1303
} ,
1309
1304
} )
1310
1305
}
0 commit comments