@@ -275,8 +275,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
275275 * err. long_ty_path ( ) = long_ty_file;
276276
277277 let mut suggested = false ;
278+ let mut noted_missing_impl = false ;
278279 if is_try_conversion || is_question_mark {
279- suggested = self . try_conversion_context ( & obligation, main_trait_predicate, & mut err) ;
280+ ( suggested, noted_missing_impl ) = self . try_conversion_context ( & obligation, main_trait_predicate, & mut err) ;
280281 }
281282
282283 if let Some ( ret_span) = self . return_type_span ( & obligation) {
@@ -335,6 +336,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
335336 return err. emit ( ) ;
336337 }
337338
339+ let ty_span = match leaf_trait_predicate. self_ty ( ) . skip_binder ( ) . kind ( ) {
340+ ty:: Adt ( def, _) if def. did ( ) . is_local ( )
341+ && !self . can_suggest_derive ( & obligation, leaf_trait_predicate) => self . tcx . def_span ( def. did ( ) ) ,
342+ _ => DUMMY_SP ,
343+ } ;
338344 if let Some ( s) = label {
339345 // If it has a custom `#[rustc_on_unimplemented]`
340346 // error message, let's display it as the label!
@@ -347,15 +353,28 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
347353 // Don't say "the trait `FromResidual<Option<Infallible>>` is
348354 // not implemented for `Result<T, E>`".
349355 {
350- err. help ( explanation) ;
356+ // We do this just so that the JSON output's `help` position is the
357+ // right one and not `file.rs:1:1`. The render is the same.
358+ if ty_span == DUMMY_SP {
359+ err. help ( explanation) ;
360+ } else {
361+ err. span_help ( ty_span, explanation) ;
362+ }
351363 }
352364 } else if let Some ( custom_explanation) = safe_transmute_explanation {
353365 err. span_label ( span, custom_explanation) ;
354- } else if explanation. len ( ) > self . tcx . sess . diagnostic_width ( ) {
366+ } else if ( explanation. len ( ) > self . tcx . sess . diagnostic_width ( ) || ty_span != DUMMY_SP ) && !noted_missing_impl {
355367 // Really long types don't look good as span labels, instead move it
356368 // to a `help`.
357369 err. span_label ( span, "unsatisfied trait bound" ) ;
358- err. help ( explanation) ;
370+
371+ // We do this just so that the JSON output's `help` position is the
372+ // right one and not `file.rs:1:1`. The render is the same.
373+ if ty_span == DUMMY_SP {
374+ err. help ( explanation) ;
375+ } else {
376+ err. span_help ( ty_span, explanation) ;
377+ }
359378 } else {
360379 err. span_label ( span, explanation) ;
361380 }
@@ -939,7 +958,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
939958 obligation : & PredicateObligation < ' tcx > ,
940959 trait_pred : ty:: PolyTraitPredicate < ' tcx > ,
941960 err : & mut Diag < ' _ > ,
942- ) -> bool {
961+ ) -> ( bool , bool ) {
943962 let span = obligation. cause . span ;
944963 /// Look for the (direct) sub-expr of `?`, and return it if it's a `.` method call.
945964 struct FindMethodSubexprOfTry {
@@ -959,21 +978,22 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
959978 }
960979 }
961980 let hir_id = self . tcx . local_def_id_to_hir_id ( obligation. cause . body_id ) ;
962- let Some ( body_id) = self . tcx . hir_node ( hir_id) . body_id ( ) else { return false } ;
981+ let Some ( body_id) = self . tcx . hir_node ( hir_id) . body_id ( ) else { return ( false , false ) } ;
963982 let ControlFlow :: Break ( expr) =
964983 ( FindMethodSubexprOfTry { search_span : span } ) . visit_body ( self . tcx . hir_body ( body_id) )
965984 else {
966- return false ;
985+ return ( false , false ) ;
967986 } ;
968987 let Some ( typeck) = & self . typeck_results else {
969- return false ;
988+ return ( false , false ) ;
970989 } ;
971990 let ObligationCauseCode :: QuestionMark = obligation. cause . code ( ) . peel_derives ( ) else {
972- return false ;
991+ return ( false , false ) ;
973992 } ;
974993 let self_ty = trait_pred. skip_binder ( ) . self_ty ( ) ;
975994 let found_ty = trait_pred. skip_binder ( ) . trait_ref . args . get ( 1 ) . and_then ( |a| a. as_type ( ) ) ;
976- self . note_missing_impl_for_question_mark ( err, self_ty, found_ty, trait_pred) ;
995+ let noted_missing_impl =
996+ self . note_missing_impl_for_question_mark ( err, self_ty, found_ty, trait_pred) ;
977997
978998 let mut prev_ty = self . resolve_vars_if_possible (
979999 typeck. expr_ty_adjusted_opt ( expr) . unwrap_or ( Ty :: new_misc_error ( self . tcx ) ) ,
@@ -1137,7 +1157,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
11371157 }
11381158 prev = Some ( err_ty) ;
11391159 }
1140- suggested
1160+ ( suggested, noted_missing_impl )
11411161 }
11421162
11431163 fn note_missing_impl_for_question_mark (
@@ -1146,7 +1166,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
11461166 self_ty : Ty < ' _ > ,
11471167 found_ty : Option < Ty < ' _ > > ,
11481168 trait_pred : ty:: PolyTraitPredicate < ' tcx > ,
1149- ) {
1169+ ) -> bool {
11501170 match ( self_ty. kind ( ) , found_ty) {
11511171 ( ty:: Adt ( def, _) , Some ( ty) )
11521172 if let ty:: Adt ( found, _) = ty. kind ( )
@@ -1187,8 +1207,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
11871207 format ! ( "`{ty}` needs to implement `Into<{self_ty}>`" ) ,
11881208 ) ;
11891209 }
1190- _ => { }
1210+ _ => return false ,
11911211 }
1212+ true
11921213 }
11931214
11941215 fn report_const_param_not_wf (
0 commit comments