@@ -254,8 +254,15 @@ pub trait TypeErrCtxtExt<'tcx> {
254254 found_span : Option < Span > ,
255255 found : ty:: PolyTraitRef < ' tcx > ,
256256 expected : ty:: PolyTraitRef < ' tcx > ,
257+ cause : & ObligationCauseCode < ' tcx > ,
257258 ) -> DiagnosticBuilder < ' tcx , ErrorGuaranteed > ;
258259
260+ fn note_conflicting_closure_bounds (
261+ & self ,
262+ cause : & ObligationCauseCode < ' tcx > ,
263+ err : & mut DiagnosticBuilder < ' tcx , ErrorGuaranteed > ,
264+ ) ;
265+
259266 fn suggest_fully_qualified_path (
260267 & self ,
261268 err : & mut Diagnostic ,
@@ -1584,6 +1591,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
15841591 found_span : Option < Span > ,
15851592 found : ty:: PolyTraitRef < ' tcx > ,
15861593 expected : ty:: PolyTraitRef < ' tcx > ,
1594+ cause : & ObligationCauseCode < ' tcx > ,
15871595 ) -> DiagnosticBuilder < ' tcx , ErrorGuaranteed > {
15881596 pub ( crate ) fn build_fn_sig_ty < ' tcx > (
15891597 infcx : & InferCtxt < ' tcx > ,
@@ -1645,9 +1653,68 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
16451653 let signature_kind = format ! ( "{argument_kind} signature" ) ;
16461654 err. note_expected_found ( & signature_kind, expected_str, & signature_kind, found_str) ;
16471655
1656+ self . note_conflicting_closure_bounds ( cause, & mut err) ;
1657+
16481658 err
16491659 }
16501660
1661+ // Add a note if there are two `Fn`-family bounds that have conflicting argument
1662+ // requirements, which will always cause a closure to have a type error.
1663+ fn note_conflicting_closure_bounds (
1664+ & self ,
1665+ cause : & ObligationCauseCode < ' tcx > ,
1666+ err : & mut DiagnosticBuilder < ' tcx , ErrorGuaranteed > ,
1667+ ) {
1668+ // First, look for an `ExprBindingObligation`, which means we can get
1669+ // the unsubstituted predicate list of the called function. And check
1670+ // that the predicate that we failed to satisfy is a `Fn`-like trait.
1671+ if let ObligationCauseCode :: ExprBindingObligation ( def_id, _, _, idx) = cause
1672+ && let predicates = self . tcx . predicates_of ( def_id) . instantiate_identity ( self . tcx )
1673+ && let Some ( pred) = predicates. predicates . get ( * idx)
1674+ && let ty:: PredicateKind :: Trait ( trait_pred) = pred. kind ( ) . skip_binder ( )
1675+ && ty:: ClosureKind :: from_def_id ( self . tcx , trait_pred. def_id ( ) ) . is_some ( )
1676+ {
1677+ let expected_self =
1678+ self . tcx . anonymize_late_bound_regions ( pred. kind ( ) . rebind ( trait_pred. self_ty ( ) ) ) ;
1679+ let expected_substs = self
1680+ . tcx
1681+ . anonymize_late_bound_regions ( pred. kind ( ) . rebind ( trait_pred. trait_ref . substs ) ) ;
1682+
1683+ // Find another predicate whose self-type is equal to the expected self type,
1684+ // but whose substs don't match.
1685+ let other_pred = std:: iter:: zip ( & predicates. predicates , & predicates. spans )
1686+ . enumerate ( )
1687+ . find ( |( other_idx, ( pred, _) ) | match pred. kind ( ) . skip_binder ( ) {
1688+ ty:: PredicateKind :: Trait ( trait_pred)
1689+ if ty:: ClosureKind :: from_def_id ( self . tcx , trait_pred. def_id ( ) )
1690+ . is_some ( )
1691+ && other_idx != idx
1692+ // Make sure that the self type matches
1693+ // (i.e. constraining this closure)
1694+ && expected_self
1695+ == self . tcx . anonymize_late_bound_regions (
1696+ pred. kind ( ) . rebind ( trait_pred. self_ty ( ) ) ,
1697+ )
1698+ // But the substs don't match (i.e. incompatible args)
1699+ && expected_substs
1700+ != self . tcx . anonymize_late_bound_regions (
1701+ pred. kind ( ) . rebind ( trait_pred. trait_ref . substs ) ,
1702+ ) =>
1703+ {
1704+ true
1705+ }
1706+ _ => false ,
1707+ } ) ;
1708+ // If we found one, then it's very likely the cause of the error.
1709+ if let Some ( ( _, ( _, other_pred_span) ) ) = other_pred {
1710+ err. span_note (
1711+ * other_pred_span,
1712+ "closure inferred to have a different signature due to this bound" ,
1713+ ) ;
1714+ }
1715+ }
1716+ }
1717+
16511718 fn suggest_fully_qualified_path (
16521719 & self ,
16531720 err : & mut Diagnostic ,
0 commit comments