Skip to content

Commit 05ca3e3

Browse files
authored
Rollup merge of #111451 - compiler-errors:note-cast-origin, r=b-naber
Note user-facing types of coercion failure When coercing, for example, `Box<A>` into `Box<dyn B>`, make sure that any failure notes mention *those* specific types, rather than mentioning inner types, like "the cast from `A` to `dyn B`". I expect end-users are often confused when we skip layers of types and only mention the "innermost" part of a coercion, especially when other notes point at HIR, e.g. #111406.
2 parents 36125c4 + 14bf909 commit 05ca3e3

File tree

65 files changed

+142
-225
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+142
-225
lines changed

compiler/rustc_middle/src/traits/mod.rs

-3
Original file line numberDiff line numberDiff line change
@@ -281,9 +281,6 @@ pub enum ObligationCauseCode<'tcx> {
281281
/// A type like `Box<Foo<'a> + 'b>` is WF only if `'b: 'a`.
282282
ObjectTypeBound(Ty<'tcx>, ty::Region<'tcx>),
283283

284-
/// Obligation incurred due to an object cast.
285-
ObjectCastObligation(/* Concrete type */ Ty<'tcx>, /* Object type */ Ty<'tcx>),
286-
287284
/// Obligation incurred due to a coercion.
288285
Coercion {
289286
source: Ty<'tcx>,

compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs

+12-4
Original file line numberDiff line numberDiff line change
@@ -797,9 +797,17 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
797797
err.span_label(span, explanation);
798798
}
799799

800-
if let ObligationCauseCode::ObjectCastObligation(concrete_ty, obj_ty) = obligation.cause.code().peel_derives() &&
801-
Some(trait_ref.def_id()) == self.tcx.lang_items().sized_trait() {
802-
self.suggest_borrowing_for_object_cast(&mut err, &root_obligation, *concrete_ty, *obj_ty);
800+
if let ObligationCauseCode::Coercion { source, target } =
801+
*obligation.cause.code().peel_derives()
802+
{
803+
if Some(trait_ref.def_id()) == self.tcx.lang_items().sized_trait() {
804+
self.suggest_borrowing_for_object_cast(
805+
&mut err,
806+
&root_obligation,
807+
source,
808+
target,
809+
);
810+
}
803811
}
804812

805813
let UnsatisfiedConst(unsatisfied_const) = self
@@ -1510,7 +1518,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
15101518
| ObligationCauseCode::BindingObligation(_, _)
15111519
| ObligationCauseCode::ExprItemObligation(..)
15121520
| ObligationCauseCode::ExprBindingObligation(..)
1513-
| ObligationCauseCode::ObjectCastObligation(..)
1521+
| ObligationCauseCode::Coercion { .. }
15141522
| ObligationCauseCode::OpaqueType
15151523
);
15161524

compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

+13-15
Original file line numberDiff line numberDiff line change
@@ -1442,8 +1442,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
14421442
err: &mut Diagnostic,
14431443
obligation: &PredicateObligation<'tcx>,
14441444
self_ty: Ty<'tcx>,
1445-
object_ty: Ty<'tcx>,
1445+
target_ty: Ty<'tcx>,
14461446
) {
1447+
let ty::Ref(_, object_ty, hir::Mutability::Not) = target_ty.kind() else { return; };
14471448
let ty::Dynamic(predicates, _, ty::Dyn) = object_ty.kind() else { return; };
14481449
let self_ref_ty = self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, self_ty);
14491450

@@ -1458,7 +1459,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
14581459
err.span_suggestion(
14591460
obligation.cause.span.shrink_to_lo(),
14601461
format!(
1461-
"consider borrowing the value, since `&{self_ty}` can be coerced into `{object_ty}`"
1462+
"consider borrowing the value, since `&{self_ty}` can be coerced into `{target_ty}`"
14621463
),
14631464
"&",
14641465
Applicability::MaybeIncorrect,
@@ -2851,30 +2852,27 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
28512852
err.span_note(tcx.def_span(item_def_id), descr);
28522853
}
28532854
}
2854-
ObligationCauseCode::ObjectCastObligation(concrete_ty, object_ty) => {
2855-
let (concrete_ty, concrete_file) =
2856-
self.tcx.short_ty_string(self.resolve_vars_if_possible(concrete_ty));
2857-
let (object_ty, object_file) =
2858-
self.tcx.short_ty_string(self.resolve_vars_if_possible(object_ty));
2855+
ObligationCauseCode::Coercion { source, target } => {
2856+
let (source, source_file) =
2857+
self.tcx.short_ty_string(self.resolve_vars_if_possible(source));
2858+
let (target, target_file) =
2859+
self.tcx.short_ty_string(self.resolve_vars_if_possible(target));
28592860
err.note(with_forced_trimmed_paths!(format!(
2860-
"required for the cast from `{concrete_ty}` to the object type `{object_ty}`",
2861+
"required for the cast from `{source}` to `{target}`",
28612862
)));
2862-
if let Some(file) = concrete_file {
2863+
if let Some(file) = source_file {
28632864
err.note(format!(
2864-
"the full name for the casted type has been written to '{}'",
2865+
"the full name for the source type has been written to '{}'",
28652866
file.display(),
28662867
));
28672868
}
2868-
if let Some(file) = object_file {
2869+
if let Some(file) = target_file {
28692870
err.note(format!(
2870-
"the full name for the object type has been written to '{}'",
2871+
"the full name for the target type has been written to '{}'",
28712872
file.display(),
28722873
));
28732874
}
28742875
}
2875-
ObligationCauseCode::Coercion { source: _, target } => {
2876-
err.note(format!("required by cast to type `{}`", self.ty_to_string(target)));
2877-
}
28782876
ObligationCauseCode::RepeatElementCopy { is_const_fn } => {
28792877
err.note(
28802878
"the `Copy` trait is required because this value will be copied for each element of the array",

compiler/rustc_trait_selection/src/traits/select/confirmation.rs

+12-24
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@ use crate::traits::{
2929
ImplSourceAutoImplData, ImplSourceBuiltinData, ImplSourceClosureData,
3030
ImplSourceConstDestructData, ImplSourceFnPointerData, ImplSourceFutureData,
3131
ImplSourceGeneratorData, ImplSourceObjectData, ImplSourceTraitAliasData,
32-
ImplSourceTraitUpcastingData, ImplSourceUserDefinedData, Normalized, ObjectCastObligation,
33-
Obligation, ObligationCause, OutputTypeParameterMismatch, PredicateObligation, Selection,
34-
SelectionError, TraitNotObjectSafe, TraitObligation, Unimplemented,
32+
ImplSourceTraitUpcastingData, ImplSourceUserDefinedData, Normalized, Obligation,
33+
ObligationCause, OutputTypeParameterMismatch, PredicateObligation, Selection, SelectionError,
34+
TraitNotObjectSafe, TraitObligation, Unimplemented,
3535
};
3636

3737
use super::BuiltinImplConditions;
@@ -905,16 +905,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
905905
.map_err(|_| Unimplemented)?;
906906
nested.extend(obligations);
907907

908-
// Register one obligation for 'a: 'b.
909-
let cause = ObligationCause::new(
910-
obligation.cause.span,
911-
obligation.cause.body_id,
912-
ObjectCastObligation(source, target),
913-
);
914908
let outlives = ty::OutlivesPredicate(r_a, r_b);
915909
nested.push(Obligation::with_depth(
916910
tcx,
917-
cause,
911+
obligation.cause.clone(),
918912
obligation.recursion_depth + 1,
919913
obligation.param_env,
920914
obligation.predicate.rebind(outlives),
@@ -1005,15 +999,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1005999
nested.extend(obligations);
10061000

10071001
// Register one obligation for 'a: 'b.
1008-
let cause = ObligationCause::new(
1009-
obligation.cause.span,
1010-
obligation.cause.body_id,
1011-
ObjectCastObligation(source, target),
1012-
);
10131002
let outlives = ty::OutlivesPredicate(r_a, r_b);
10141003
nested.push(Obligation::with_depth(
10151004
tcx,
1016-
cause,
1005+
obligation.cause.clone(),
10171006
obligation.recursion_depth + 1,
10181007
obligation.param_env,
10191008
obligation.predicate.rebind(outlives),
@@ -1027,16 +1016,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
10271016
return Err(TraitNotObjectSafe(did));
10281017
}
10291018

1030-
let cause = ObligationCause::new(
1031-
obligation.cause.span,
1032-
obligation.cause.body_id,
1033-
ObjectCastObligation(source, target),
1034-
);
1035-
10361019
let predicate_to_obligation = |predicate| {
10371020
Obligation::with_depth(
10381021
tcx,
1039-
cause.clone(),
1022+
obligation.cause.clone(),
10401023
obligation.recursion_depth + 1,
10411024
obligation.param_env,
10421025
predicate,
@@ -1056,7 +1039,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
10561039
);
10571040

10581041
// We can only make objects from sized types.
1059-
let tr = ty::TraitRef::from_lang_item(tcx, LangItem::Sized, cause.span, [source]);
1042+
let tr = ty::TraitRef::from_lang_item(
1043+
tcx,
1044+
LangItem::Sized,
1045+
obligation.cause.span,
1046+
[source],
1047+
);
10601048
nested.push(predicate_to_obligation(tr.without_const().to_predicate(tcx)));
10611049

10621050
// If the type is `Foo + 'a`, ensure that the type

compiler/rustc_trait_selection/src/traits/select/mod.rs

+13-8
Original file line numberDiff line numberDiff line change
@@ -2647,14 +2647,19 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
26472647
let predicates = predicates.instantiate_own(tcx, substs);
26482648
let mut obligations = Vec::with_capacity(predicates.len());
26492649
for (index, (predicate, span)) in predicates.into_iter().enumerate() {
2650-
let cause = cause.clone().derived_cause(parent_trait_pred, |derived| {
2651-
ImplDerivedObligation(Box::new(ImplDerivedObligationCause {
2652-
derived,
2653-
impl_or_alias_def_id: def_id,
2654-
impl_def_predicate_index: Some(index),
2655-
span,
2656-
}))
2657-
});
2650+
let cause =
2651+
if Some(parent_trait_pred.def_id()) == tcx.lang_items().coerce_unsized_trait() {
2652+
cause.clone()
2653+
} else {
2654+
cause.clone().derived_cause(parent_trait_pred, |derived| {
2655+
ImplDerivedObligation(Box::new(ImplDerivedObligationCause {
2656+
derived,
2657+
impl_or_alias_def_id: def_id,
2658+
impl_def_predicate_index: Some(index),
2659+
span,
2660+
}))
2661+
})
2662+
};
26582663
let predicate = normalize_with_depth_to(
26592664
self,
26602665
param_env,

tests/ui/associated-types/associated-types-eq-3.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ note: expected this to be `Bar`
4343
|
4444
LL | type A = usize;
4545
| ^^^^^
46-
= note: required for the cast from `isize` to the object type `dyn Foo<A = Bar>`
46+
= note: required for the cast from `&isize` to `&dyn Foo<A = Bar>`
4747

4848
error: aborting due to 3 previous errors
4949

tests/ui/associated-types/associated-types-overridden-binding-2.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error[E0271]: expected `IntoIter<u32>` to be an iterator that yields `i32`, but
44
LL | let _: &dyn I32Iterator<Item = u32> = &vec![42].into_iter();
55
| ^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `u32`
66
|
7-
= note: required for the cast from `std::vec::IntoIter<u32>` to the object type `dyn Iterator<Item = u32, Item = i32>`
7+
= note: required for the cast from `&std::vec::IntoIter<u32>` to `&dyn Iterator<Item = u32, Item = i32>`
88

99
error: aborting due to previous error
1010

tests/ui/associated-types/issue-65774-1.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ LL | impl<'a, T: MyDisplay> MyDisplay for &'a mut T { }
2525
| --------- ^^^^^^^^^ ^^^^^^^^^
2626
| |
2727
| unsatisfied trait bound introduced here
28-
= note: required for the cast from `&mut T` to the object type `dyn MyDisplay`
28+
= note: required for the cast from `&&mut T` to `&dyn MyDisplay`
2929

3030
error: aborting due to 2 previous errors
3131

tests/ui/associated-types/issue-65774-2.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ LL | writer.my_write(valref)
1818
| ^^^^^^ the trait `MyDisplay` is not implemented for `T`
1919
|
2020
= help: the trait `MyDisplay` is implemented for `&'a mut T`
21-
= note: required for the cast from `T` to the object type `dyn MyDisplay`
21+
= note: required for the cast from `&mut T` to `&dyn MyDisplay`
2222

2323
error: aborting due to 2 previous errors
2424

tests/ui/async-await/async-block-control-flow-static-semantics.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ error[E0271]: expected `[async block@$DIR/async-block-control-flow-static-semant
3535
LL | let _: &dyn Future<Output = ()> = &block;
3636
| ^^^^^^ expected `()`, found `u8`
3737
|
38-
= note: required for the cast from `[async block@$DIR/async-block-control-flow-static-semantics.rs:23:17: 25:6]` to the object type `dyn Future<Output = ()>`
38+
= note: required for the cast from `&[async block@$DIR/async-block-control-flow-static-semantics.rs:23:17: 25:6]` to `&dyn Future<Output = ()>`
3939

4040
error[E0308]: mismatched types
4141
--> $DIR/async-block-control-flow-static-semantics.rs:12:43
@@ -51,7 +51,7 @@ error[E0271]: expected `[async block@$DIR/async-block-control-flow-static-semant
5151
LL | let _: &dyn Future<Output = ()> = &block;
5252
| ^^^^^^ expected `()`, found `u8`
5353
|
54-
= note: required for the cast from `[async block@$DIR/async-block-control-flow-static-semantics.rs:14:17: 16:6]` to the object type `dyn Future<Output = ()>`
54+
= note: required for the cast from `&[async block@$DIR/async-block-control-flow-static-semantics.rs:14:17: 16:6]` to `&dyn Future<Output = ()>`
5555

5656
error[E0308]: mismatched types
5757
--> $DIR/async-block-control-flow-static-semantics.rs:49:44

tests/ui/async-await/issue-86507.drop_tracking.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ note: captured value is not `Send` because `&` references cannot be sent unless
1313
|
1414
LL | let x = x;
1515
| ^ has type `&T` which is not `Send`, because `T` is not `Sync`
16-
= note: required for the cast from `[async block@$DIR/issue-86507.rs:21:17: 23:18]` to the object type `dyn Future<Output = ()> + Send`
16+
= note: required for the cast from `Pin<Box<[async block@$DIR/issue-86507.rs:21:17: 23:18]>>` to `Pin<Box<(dyn Future<Output = ()> + Send + 'async_trait)>>`
1717
help: consider further restricting this bound
1818
|
1919
LL | fn bar<'me, 'async_trait, T: Send + std::marker::Sync>(x: &'me T)

tests/ui/async-await/issue-86507.drop_tracking_mir.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ note: captured value is not `Send` because `&` references cannot be sent unless
1313
|
1414
LL | let x = x;
1515
| ^ has type `&T` which is not `Send`, because `T` is not `Sync`
16-
= note: required for the cast from `[async block@$DIR/issue-86507.rs:21:17: 23:18]` to the object type `dyn Future<Output = ()> + Send`
16+
= note: required for the cast from `Pin<Box<[async block@$DIR/issue-86507.rs:21:17: 23:18]>>` to `Pin<Box<(dyn Future<Output = ()> + Send + 'async_trait)>>`
1717
help: consider further restricting this bound
1818
|
1919
LL | fn bar<'me, 'async_trait, T: Send + std::marker::Sync>(x: &'me T)

tests/ui/async-await/issue-86507.no_drop_tracking.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ note: captured value is not `Send` because `&` references cannot be sent unless
1313
|
1414
LL | let x = x;
1515
| ^ has type `&T` which is not `Send`, because `T` is not `Sync`
16-
= note: required for the cast from `[async block@$DIR/issue-86507.rs:21:17: 23:18]` to the object type `dyn Future<Output = ()> + Send`
16+
= note: required for the cast from `Pin<Box<[async block@$DIR/issue-86507.rs:21:17: 23:18]>>` to `Pin<Box<(dyn Future<Output = ()> + Send + 'async_trait)>>`
1717
help: consider further restricting this bound
1818
|
1919
LL | fn bar<'me, 'async_trait, T: Send + std::marker::Sync>(x: &'me T)

tests/ui/closure_context/issue-26046-fn-mut.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ LL | num += 1;
99
LL | Box::new(closure)
1010
| ----------------- the requirement to implement `Fn` derives from here
1111
|
12-
= note: required for the cast from `[closure@$DIR/issue-26046-fn-mut.rs:4:19: 4:21]` to the object type `dyn Fn()`
12+
= note: required for the cast from `Box<[closure@$DIR/issue-26046-fn-mut.rs:4:19: 4:21]>` to `Box<(dyn Fn() + 'static)>`
1313

1414
error: aborting due to previous error
1515

tests/ui/closure_context/issue-26046-fn-once.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ LL | vec
99
LL | Box::new(closure)
1010
| ----------------- the requirement to implement `Fn` derives from here
1111
|
12-
= note: required for the cast from `[closure@$DIR/issue-26046-fn-once.rs:4:19: 4:26]` to the object type `dyn Fn() -> Vec<u8>`
12+
= note: required for the cast from `Box<[closure@$DIR/issue-26046-fn-once.rs:4:19: 4:26]>` to `Box<(dyn Fn() -> Vec<u8> + 'static)>`
1313

1414
error: aborting due to previous error
1515

tests/ui/coercion/coerce-issue-49593-box-never-windows.nofallback.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ error[E0277]: the trait bound `(): std::error::Error` is not satisfied
44
LL | /* *mut $0 is coerced to Box<dyn Error> here */ Box::<_ /* ! */>::new(x)
55
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()`
66
|
7-
= note: required for the cast from `()` to the object type `dyn std::error::Error`
7+
= note: required for the cast from `Box<()>` to `Box<(dyn std::error::Error + 'static)>`
88

99
error[E0277]: the trait bound `(): std::error::Error` is not satisfied
1010
--> $DIR/coerce-issue-49593-box-never-windows.rs:23:49
1111
|
1212
LL | /* *mut $0 is coerced to *mut Error here */ raw_ptr_box::<_ /* ! */>(x)
1313
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()`
1414
|
15-
= note: required for the cast from `()` to the object type `(dyn std::error::Error + 'static)`
15+
= note: required for the cast from `*mut ()` to `*mut (dyn std::error::Error + 'static)`
1616

1717
error: aborting due to 2 previous errors
1818

tests/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ error[E0277]: the trait bound `(): std::error::Error` is not satisfied
44
LL | /* *mut $0 is coerced to Box<dyn Error> here */ Box::<_ /* ! */>::new(x)
55
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()`
66
|
7-
= note: required for the cast from `()` to the object type `dyn std::error::Error`
7+
= note: required for the cast from `Box<()>` to `Box<(dyn std::error::Error + 'static)>`
88

99
error[E0277]: the trait bound `(): std::error::Error` is not satisfied
1010
--> $DIR/coerce-issue-49593-box-never.rs:23:49
1111
|
1212
LL | /* *mut $0 is coerced to *mut Error here */ raw_ptr_box::<_ /* ! */>(x)
1313
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()`
1414
|
15-
= note: required for the cast from `()` to the object type `(dyn std::error::Error + 'static)`
15+
= note: required for the cast from `*mut ()` to `*mut (dyn std::error::Error + 'static)`
1616

1717
error: aborting due to 2 previous errors
1818

tests/ui/const-generics/defaults/trait_objects_fail.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ LL | foo(&10_u32);
55
| ^^^^^^^ the trait `Trait` is not implemented for `u32`
66
|
77
= help: the trait `Trait<2>` is implemented for `u32`
8-
= note: required for the cast from `u32` to the object type `dyn Trait`
8+
= note: required for the cast from `&u32` to `&dyn Trait`
99

1010
error[E0277]: the trait bound `bool: Traitor<_>` is not satisfied
1111
--> $DIR/trait_objects_fail.rs:28:9
@@ -14,7 +14,7 @@ LL | bar(&true);
1414
| ^^^^^ the trait `Traitor<_>` is not implemented for `bool`
1515
|
1616
= help: the trait `Traitor<2, 3>` is implemented for `bool`
17-
= note: required for the cast from `bool` to the object type `dyn Traitor<_>`
17+
= note: required for the cast from `&bool` to `&dyn Traitor<_>`
1818

1919
error: aborting due to 2 previous errors
2020

tests/ui/custom_test_frameworks/mismatch.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ LL | #[test]
66
LL | fn wrong_kind(){}
77
| ^^^^^^^^^^^^^^^^^ the trait `Testable` is not implemented for `TestDescAndFn`
88
|
9-
= note: required for the cast from `TestDescAndFn` to the object type `dyn Testable`
9+
= note: required for the cast from `&TestDescAndFn` to `&dyn Testable`
1010
= note: this error originates in the attribute macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)
1111

1212
error: aborting due to previous error

0 commit comments

Comments
 (0)