@@ -1429,13 +1429,23 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
14291429 }
14301430 }
14311431
1432+ /// Extend a type error with extra labels pointing at "non-trivial" types, like closures and
1433+ /// the return type of `async fn`s.
1434+ ///
1435+ /// `secondary_span` gives the caller the opportunity to expand `diag` with a `span_label`.
1436+ ///
1437+ /// `swap_secondary_and_primary` is used to make projection errors in particular nicer by using
1438+ /// the message in `secondary_span` as the primary label, and apply the message that would
1439+ /// otherwise be used for the primary label on the `secondary_span` `Span`. This applies on
1440+ /// E0271, like `src/test/ui/issues/issue-39970.stderr`.
14321441 pub fn note_type_err (
14331442 & self ,
14341443 diag : & mut DiagnosticBuilder < ' tcx > ,
14351444 cause : & ObligationCause < ' tcx > ,
14361445 secondary_span : Option < ( Span , String ) > ,
14371446 mut values : Option < ValuePairs < ' tcx > > ,
14381447 terr : & TypeError < ' tcx > ,
1448+ swap_secondary_and_primary : bool ,
14391449 ) {
14401450 let span = cause. span ( self . tcx ) ;
14411451 debug ! ( "note_type_err cause={:?} values={:?}, terr={:?}" , cause, values, terr) ;
@@ -1612,9 +1622,32 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
16121622 match terr {
16131623 TypeError :: ObjectUnsafeCoercion ( _) => { }
16141624 _ => {
1615- diag. span_label ( span, terr. to_string ( ) ) ;
1625+ let mut label_or_note = |span : Span , msg : & str | {
1626+ if & [ span] == diag. span . primary_spans ( ) {
1627+ diag. span_label ( span, msg) ;
1628+ } else {
1629+ diag. span_note ( span, msg) ;
1630+ }
1631+ } ;
16161632 if let Some ( ( sp, msg) ) = secondary_span {
1617- diag. span_label ( sp, msg) ;
1633+ if swap_secondary_and_primary {
1634+ let terr = if let Some ( infer:: ValuePairs :: Types ( infer:: ExpectedFound {
1635+ expected,
1636+ ..
1637+ } ) ) = values
1638+ {
1639+ format ! ( "expected this to be `{}`" , expected)
1640+ } else {
1641+ terr. to_string ( )
1642+ } ;
1643+ label_or_note ( sp, & terr) ;
1644+ label_or_note ( span, & msg) ;
1645+ } else {
1646+ label_or_note ( span, & terr. to_string ( ) ) ;
1647+ label_or_note ( sp, & msg) ;
1648+ }
1649+ } else {
1650+ label_or_note ( span, & terr. to_string ( ) ) ;
16181651 }
16191652 }
16201653 } ;
@@ -2048,7 +2081,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
20482081 struct_span_err ! ( self . tcx. sess, span, E0644 , "{}" , failure_str)
20492082 }
20502083 } ;
2051- self . note_type_err ( & mut diag, & trace. cause , None , Some ( trace. values ) , terr) ;
2084+ self . note_type_err ( & mut diag, & trace. cause , None , Some ( trace. values ) , terr, false ) ;
20522085 diag
20532086 }
20542087
0 commit comments