@@ -27,13 +27,14 @@ use rustc_infer::infer::InferOk;
2727use rustc_infer:: infer:: TypeTrace ;
2828use rustc_middle:: ty:: adjustment:: AllowTwoPhase ;
2929use rustc_middle:: ty:: visit:: TypeVisitable ;
30- use rustc_middle:: ty:: { self , DefIdTree , IsSuggestable , Ty } ;
30+ use rustc_middle:: ty:: { self , DefIdTree , IsSuggestable , Ty , TypeSuperVisitable , TypeVisitor } ;
3131use rustc_session:: Session ;
3232use rustc_span:: symbol:: Ident ;
3333use rustc_span:: { self , Span } ;
3434use rustc_trait_selection:: traits:: { self , ObligationCauseCode , SelectionContext } ;
3535
3636use std:: iter;
37+ use std:: ops:: ControlFlow ;
3738use std:: slice;
3839
3940impl < ' a , ' tcx > FnCtxt < ' a , ' tcx > {
@@ -1649,7 +1650,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16491650 ty:: PredicateKind :: Projection ( pred) => pred. projection_ty . substs ,
16501651 _ => ty:: List :: empty ( ) ,
16511652 } ;
1652- let param_to_point_at = predicate_substs. types ( ) . find_map ( |ty| {
1653+ let mut param_to_point_at = predicate_substs. types ( ) . find_map ( |ty| {
16531654 ty. walk ( ) . find_map ( |arg| {
16541655 if let ty:: GenericArgKind :: Type ( ty) = arg. unpack ( )
16551656 && let ty:: Param ( param_ty) = ty. kind ( )
@@ -1663,7 +1664,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16631664 }
16641665 } )
16651666 } ) ;
1666- let fallback_param_to_point_at = predicate_substs. types ( ) . find_map ( |ty| {
1667+ let mut fallback_param_to_point_at = predicate_substs. types ( ) . find_map ( |ty| {
16671668 ty. walk ( ) . find_map ( |arg| {
16681669 if let ty:: GenericArgKind :: Type ( ty) = arg. unpack ( )
16691670 && let ty:: Param ( param_ty) = ty. kind ( )
@@ -1676,6 +1677,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16761677 } )
16771678 } ) ;
16781679
1680+ // Also skip over ambiguity errors, which have their own machinery
1681+ // to print a relevant error.
1682+ if let traits:: FulfillmentErrorCode :: CodeAmbiguity = error. code {
1683+ fallback_param_to_point_at = None ;
1684+ param_to_point_at =
1685+ self . find_ambiguous_parameter_in ( def_id, error. root_obligation . predicate ) ;
1686+ }
1687+
16791688 let hir = self . tcx . hir ( ) ;
16801689
16811690 match hir. get ( hir_id) {
@@ -1737,6 +1746,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
17371746 }
17381747 }
17391748
1749+ fn find_ambiguous_parameter_in < T : TypeVisitable < ' tcx > > (
1750+ & self ,
1751+ item_def_id : DefId ,
1752+ t : T ,
1753+ ) -> Option < ty:: GenericArg < ' tcx > > {
1754+ struct FindAmbiguousParameter < ' a , ' tcx > ( & ' a FnCtxt < ' a , ' tcx > , DefId ) ;
1755+ impl < ' tcx > TypeVisitor < ' tcx > for FindAmbiguousParameter < ' _ , ' tcx > {
1756+ type BreakTy = ty:: GenericArg < ' tcx > ;
1757+ fn visit_ty ( & mut self , ty : Ty < ' tcx > ) -> std:: ops:: ControlFlow < Self :: BreakTy > {
1758+ if let Some ( origin) = self . 0 . type_var_origin ( ty)
1759+ && let TypeVariableOriginKind :: TypeParameterDefinition ( _, Some ( def_id) )
1760+ = origin. kind
1761+ && let generics = self . 0 . tcx . generics_of ( self . 1 )
1762+ && let Some ( index) = generics. param_def_id_to_index ( self . 0 . tcx , def_id)
1763+ && let Some ( subst) = ty:: InternalSubsts :: identity_for_item ( self . 0 . tcx , self . 1 ) . get ( index as usize )
1764+ {
1765+ ControlFlow :: Break ( * subst)
1766+ } else {
1767+ ty. super_visit_with ( self )
1768+ }
1769+ }
1770+ }
1771+ t. visit_with ( & mut FindAmbiguousParameter ( self , item_def_id) ) . break_value ( )
1772+ }
1773+
17401774 fn point_at_args_if_possible (
17411775 & self ,
17421776 error : & mut traits:: FulfillmentError < ' tcx > ,
0 commit comments