@@ -275,8 +275,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
275
275
* err. long_ty_path ( ) = long_ty_file;
276
276
277
277
let mut suggested = false ;
278
+ let mut noted_missing_impl = false ;
278
279
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) ;
280
281
}
281
282
282
283
if let Some ( ret_span) = self . return_type_span ( & obligation) {
@@ -335,6 +336,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
335
336
return err. emit ( ) ;
336
337
}
337
338
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
+ } ;
338
344
if let Some ( s) = label {
339
345
// If it has a custom `#[rustc_on_unimplemented]`
340
346
// error message, let's display it as the label!
@@ -347,15 +353,28 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
347
353
// Don't say "the trait `FromResidual<Option<Infallible>>` is
348
354
// not implemented for `Result<T, E>`".
349
355
{
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
+ }
351
363
}
352
364
} else if let Some ( custom_explanation) = safe_transmute_explanation {
353
365
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 {
355
367
// Really long types don't look good as span labels, instead move it
356
368
// to a `help`.
357
369
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
+ }
359
378
} else {
360
379
err. span_label ( span, explanation) ;
361
380
}
@@ -939,7 +958,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
939
958
obligation : & PredicateObligation < ' tcx > ,
940
959
trait_pred : ty:: PolyTraitPredicate < ' tcx > ,
941
960
err : & mut Diag < ' _ > ,
942
- ) -> bool {
961
+ ) -> ( bool , bool ) {
943
962
let span = obligation. cause . span ;
944
963
/// Look for the (direct) sub-expr of `?`, and return it if it's a `.` method call.
945
964
struct FindMethodSubexprOfTry {
@@ -959,21 +978,22 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
959
978
}
960
979
}
961
980
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 ) } ;
963
982
let ControlFlow :: Break ( expr) =
964
983
( FindMethodSubexprOfTry { search_span : span } ) . visit_body ( self . tcx . hir_body ( body_id) )
965
984
else {
966
- return false ;
985
+ return ( false , false ) ;
967
986
} ;
968
987
let Some ( typeck) = & self . typeck_results else {
969
- return false ;
988
+ return ( false , false ) ;
970
989
} ;
971
990
let ObligationCauseCode :: QuestionMark = obligation. cause . code ( ) . peel_derives ( ) else {
972
- return false ;
991
+ return ( false , false ) ;
973
992
} ;
974
993
let self_ty = trait_pred. skip_binder ( ) . self_ty ( ) ;
975
994
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) ;
977
997
978
998
let mut prev_ty = self . resolve_vars_if_possible (
979
999
typeck. expr_ty_adjusted_opt ( expr) . unwrap_or ( Ty :: new_misc_error ( self . tcx ) ) ,
@@ -1137,7 +1157,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
1137
1157
}
1138
1158
prev = Some ( err_ty) ;
1139
1159
}
1140
- suggested
1160
+ ( suggested, noted_missing_impl )
1141
1161
}
1142
1162
1143
1163
fn note_missing_impl_for_question_mark (
@@ -1146,7 +1166,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
1146
1166
self_ty : Ty < ' _ > ,
1147
1167
found_ty : Option < Ty < ' _ > > ,
1148
1168
trait_pred : ty:: PolyTraitPredicate < ' tcx > ,
1149
- ) {
1169
+ ) -> bool {
1150
1170
match ( self_ty. kind ( ) , found_ty) {
1151
1171
( ty:: Adt ( def, _) , Some ( ty) )
1152
1172
if let ty:: Adt ( found, _) = ty. kind ( )
@@ -1187,8 +1207,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
1187
1207
format ! ( "`{ty}` needs to implement `Into<{self_ty}>`" ) ,
1188
1208
) ;
1189
1209
}
1190
- _ => { }
1210
+ _ => return false ,
1191
1211
}
1212
+ true
1192
1213
}
1193
1214
1194
1215
fn report_const_param_not_wf (
0 commit comments