Point at type that doesn't implement needed trait
``` error[E0277]: `?` couldn't convert the error: `E: std::error::Error` is not satisfied --> $DIR/bad-question-mark-on-trait-object.rs:7:13 | LL | fn foo() -> Result<(), Box<dyn std::error::Error>> { | -------------------------------------- required `E: std::error::Error` because of this LL | Ok(bar()?) | -----^ the trait `std::error::Error` is not implemented for `E` | | | this has type `Result<_, E>` | note: `E` needs to implement `std::error::Error` --> $DIR/bad-question-mark-on-trait-object.rs:1:1 | LL | struct E; | ^^^^^^^^ = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait = note: required for `Box<dyn std::error::Error>` to implement `From<E>` error[E0277]: `?` couldn't convert the error to `X` --> $DIR/bad-question-mark-on-trait-object.rs:18:13 | LL | fn bat() -> Result<(), X> { | ------------- expected `X` because of this LL | Ok(bar()?) | -----^ the trait `From<E>` is not implemented for `X` | | | this can't be annotated with `?` because it has type `Result<_, E>` | note: `X` needs to implement `From<E>` --> $DIR/bad-question-mark-on-trait-object.rs:4:1 | LL | struct X; | ^^^^^^^^ note: alternatively, `E` needs to implement `Into<X>` --> $DIR/bad-question-mark-on-trait-object.rs:1:1 | LL | struct E; | ^^^^^^^^ = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait ```
This commit is contained in:
parent
8ef535e03d
commit
31febc684b
3 changed files with 71 additions and 3 deletions
|
@ -966,6 +966,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
};
|
||||
let self_ty = trait_pred.skip_binder().self_ty();
|
||||
let found_ty = trait_pred.skip_binder().trait_ref.args.get(1).and_then(|a| a.as_type());
|
||||
self.note_missing_impl_for_question_mark(err, self_ty, found_ty, trait_pred);
|
||||
|
||||
let mut prev_ty = self.resolve_vars_if_possible(
|
||||
typeck.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(self.tcx)),
|
||||
|
@ -1130,6 +1131,56 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
suggested
|
||||
}
|
||||
|
||||
fn note_missing_impl_for_question_mark(
|
||||
&self,
|
||||
err: &mut Diag<'_>,
|
||||
self_ty: Ty<'_>,
|
||||
found_ty: Option<Ty<'_>>,
|
||||
trait_pred: ty::PolyTraitPredicate<'tcx>,
|
||||
) {
|
||||
match (self_ty.kind(), found_ty) {
|
||||
(ty::Adt(def, _), Some(ty))
|
||||
if let ty::Adt(found, _) = ty.kind()
|
||||
&& def.did().is_local()
|
||||
&& found.did().is_local() =>
|
||||
{
|
||||
err.span_note(
|
||||
self.tcx.def_span(def.did()),
|
||||
format!("`{self_ty}` needs to implement `From<{ty}>`"),
|
||||
);
|
||||
err.span_note(
|
||||
self.tcx.def_span(found.did()),
|
||||
format!("alternatively, `{ty}` needs to implement `Into<{self_ty}>`"),
|
||||
);
|
||||
}
|
||||
(ty::Adt(def, _), None) if def.did().is_local() => {
|
||||
err.span_note(
|
||||
self.tcx.def_span(def.did()),
|
||||
format!(
|
||||
"`{self_ty}` needs to implement `{}`",
|
||||
trait_pred.skip_binder().trait_ref.print_only_trait_path(),
|
||||
),
|
||||
);
|
||||
}
|
||||
(ty::Adt(def, _), Some(ty)) if def.did().is_local() => {
|
||||
err.span_note(
|
||||
self.tcx.def_span(def.did()),
|
||||
format!("`{self_ty}` needs to implement `From<{ty}>`"),
|
||||
);
|
||||
}
|
||||
(_, Some(ty))
|
||||
if let ty::Adt(def, _) = ty.kind()
|
||||
&& def.did().is_local() =>
|
||||
{
|
||||
err.span_note(
|
||||
self.tcx.def_span(def.did()),
|
||||
format!("`{ty}` needs to implement `Into<{self_ty}>`"),
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn report_const_param_not_wf(
|
||||
&self,
|
||||
ty: Ty<'tcx>,
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
struct E;
|
||||
struct X;
|
||||
//~^ NOTE `E` needs to implement `std::error::Error`
|
||||
//~| NOTE alternatively, `E` needs to implement `Into<X>`
|
||||
struct X; //~ NOTE `X` needs to implement `From<E>`
|
||||
|
||||
fn foo() -> Result<(), Box<dyn std::error::Error>> { //~ NOTE required `E: std::error::Error` because of this
|
||||
Ok(bar()?)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error[E0277]: `?` couldn't convert the error: `E: std::error::Error` is not satisfied
|
||||
--> $DIR/bad-question-mark-on-trait-object.rs:5:13
|
||||
--> $DIR/bad-question-mark-on-trait-object.rs:7:13
|
||||
|
|
||||
LL | fn foo() -> Result<(), Box<dyn std::error::Error>> {
|
||||
| -------------------------------------- required `E: std::error::Error` because of this
|
||||
|
@ -8,11 +8,16 @@ LL | Ok(bar()?)
|
|||
| |
|
||||
| this has type `Result<_, E>`
|
||||
|
|
||||
note: `E` needs to implement `std::error::Error`
|
||||
--> $DIR/bad-question-mark-on-trait-object.rs:1:1
|
||||
|
|
||||
LL | struct E;
|
||||
| ^^^^^^^^
|
||||
= note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
|
||||
= note: required for `Box<dyn std::error::Error>` to implement `From<E>`
|
||||
|
||||
error[E0277]: `?` couldn't convert the error to `X`
|
||||
--> $DIR/bad-question-mark-on-trait-object.rs:16:13
|
||||
--> $DIR/bad-question-mark-on-trait-object.rs:18:13
|
||||
|
|
||||
LL | fn bat() -> Result<(), X> {
|
||||
| ------------- expected `X` because of this
|
||||
|
@ -21,6 +26,16 @@ LL | Ok(bar()?)
|
|||
| |
|
||||
| this can't be annotated with `?` because it has type `Result<_, E>`
|
||||
|
|
||||
note: `X` needs to implement `From<E>`
|
||||
--> $DIR/bad-question-mark-on-trait-object.rs:4:1
|
||||
|
|
||||
LL | struct X;
|
||||
| ^^^^^^^^
|
||||
note: alternatively, `E` needs to implement `Into<X>`
|
||||
--> $DIR/bad-question-mark-on-trait-object.rs:1:1
|
||||
|
|
||||
LL | struct E;
|
||||
| ^^^^^^^^
|
||||
= note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue