Rollup merge of #71409 - estebank:point-at-ret-question-mark-op, r=petrochenkov
Point at the return type on `.into()` failure caused by `?` Fix #35946.
This commit is contained in:
commit
c95bcbc9d5
@ -317,20 +317,30 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||||||
.starts_with("std::convert::From<std::option::NoneError");
|
.starts_with("std::convert::From<std::option::NoneError");
|
||||||
let should_convert_result_to_option = format!("{}", trait_ref)
|
let should_convert_result_to_option = format!("{}", trait_ref)
|
||||||
.starts_with("<std::option::NoneError as std::convert::From<");
|
.starts_with("<std::option::NoneError as std::convert::From<");
|
||||||
if is_try && is_from && should_convert_option_to_result {
|
if is_try && is_from {
|
||||||
err.span_suggestion_verbose(
|
if should_convert_option_to_result {
|
||||||
span.shrink_to_lo(),
|
err.span_suggestion_verbose(
|
||||||
"consider converting the `Option<T>` into a `Result<T, _>` using `Option::ok_or` or `Option::ok_or_else`",
|
span.shrink_to_lo(),
|
||||||
".ok_or_else(|| /* error value */)".to_string(),
|
"consider converting the `Option<T>` into a `Result<T, _>` \
|
||||||
Applicability::HasPlaceholders,
|
using `Option::ok_or` or `Option::ok_or_else`",
|
||||||
);
|
".ok_or_else(|| /* error value */)".to_string(),
|
||||||
} else if is_try && is_from && should_convert_result_to_option {
|
Applicability::HasPlaceholders,
|
||||||
err.span_suggestion_verbose(
|
);
|
||||||
span.shrink_to_lo(),
|
} else if should_convert_result_to_option {
|
||||||
"consider converting the `Result<T, _>` into an `Option<T>` using `Result::ok`",
|
err.span_suggestion_verbose(
|
||||||
".ok()".to_string(),
|
span.shrink_to_lo(),
|
||||||
Applicability::MachineApplicable,
|
"consider converting the `Result<T, _>` into an `Option<T>` \
|
||||||
);
|
using `Result::ok`",
|
||||||
|
".ok()".to_string(),
|
||||||
|
Applicability::MachineApplicable,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if let Some(ret_span) = self.return_type_span(obligation) {
|
||||||
|
err.span_label(
|
||||||
|
ret_span,
|
||||||
|
&format!("expected `{}` because of this", trait_ref.self_ty()),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let explanation =
|
let explanation =
|
||||||
|
@ -84,6 +84,8 @@ pub trait InferCtxtExt<'tcx> {
|
|||||||
trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
|
trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
fn return_type_span(&self, obligation: &PredicateObligation<'tcx>) -> Option<Span>;
|
||||||
|
|
||||||
fn suggest_impl_trait(
|
fn suggest_impl_trait(
|
||||||
&self,
|
&self,
|
||||||
err: &mut DiagnosticBuilder<'tcx>,
|
err: &mut DiagnosticBuilder<'tcx>,
|
||||||
@ -761,6 +763,17 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn return_type_span(&self, obligation: &PredicateObligation<'tcx>) -> Option<Span> {
|
||||||
|
let hir = self.tcx.hir();
|
||||||
|
let parent_node = hir.get_parent_node(obligation.cause.body_id);
|
||||||
|
let sig = match hir.find(parent_node) {
|
||||||
|
Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, ..), .. })) => sig,
|
||||||
|
_ => return None,
|
||||||
|
};
|
||||||
|
|
||||||
|
if let hir::FnRetTy::Return(ret_ty) = sig.decl.output { Some(ret_ty.span) } else { None }
|
||||||
|
}
|
||||||
|
|
||||||
/// If all conditions are met to identify a returned `dyn Trait`, suggest using `impl Trait` if
|
/// If all conditions are met to identify a returned `dyn Trait`, suggest using `impl Trait` if
|
||||||
/// applicable and signal that the error has been expanded appropriately and needs to be
|
/// applicable and signal that the error has been expanded appropriately and needs to be
|
||||||
/// emitted.
|
/// emitted.
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
error[E0277]: `?` couldn't convert the error to `()`
|
error[E0277]: `?` couldn't convert the error to `()`
|
||||||
--> $DIR/issue-32709.rs:4:11
|
--> $DIR/issue-32709.rs:4:11
|
||||||
|
|
|
|
||||||
|
LL | fn a() -> Result<i32, ()> {
|
||||||
|
| --------------- expected `()` because of this
|
||||||
LL | Err(5)?;
|
LL | Err(5)?;
|
||||||
| ^ the trait `std::convert::From<{integer}>` is not implemented for `()`
|
| ^ the trait `std::convert::From<{integer}>` is not implemented for `()`
|
||||||
|
|
|
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
error[E0277]: `?` couldn't convert the error to `()`
|
error[E0277]: `?` couldn't convert the error to `()`
|
||||||
--> $DIR/option-to-result.rs:5:6
|
--> $DIR/option-to-result.rs:5:6
|
||||||
|
|
|
|
||||||
|
LL | fn test_result() -> Result<(),()> {
|
||||||
|
| ------------- expected `()` because of this
|
||||||
|
LL | let a:Option<()> = Some(());
|
||||||
LL | a?;
|
LL | a?;
|
||||||
| ^ the trait `std::convert::From<std::option::NoneError>` is not implemented for `()`
|
| ^ the trait `std::convert::From<std::option::NoneError>` is not implemented for `()`
|
||||||
|
|
|
|
||||||
@ -14,6 +17,9 @@ LL | a.ok_or_else(|| /* error value */)?;
|
|||||||
error[E0277]: `?` couldn't convert the error to `std::option::NoneError`
|
error[E0277]: `?` couldn't convert the error to `std::option::NoneError`
|
||||||
--> $DIR/option-to-result.rs:11:6
|
--> $DIR/option-to-result.rs:11:6
|
||||||
|
|
|
|
||||||
|
LL | fn test_option() -> Option<i32>{
|
||||||
|
| ----------- expected `std::option::NoneError` because of this
|
||||||
|
LL | let a:Result<i32, i32> = Ok(5);
|
||||||
LL | a?;
|
LL | a?;
|
||||||
| ^ the trait `std::convert::From<i32>` is not implemented for `std::option::NoneError`
|
| ^ the trait `std::convert::From<i32>` is not implemented for `std::option::NoneError`
|
||||||
|
|
|
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
error[E0277]: `?` couldn't convert the error to `()`
|
error[E0277]: `?` couldn't convert the error to `()`
|
||||||
--> $DIR/try-on-option.rs:7:6
|
--> $DIR/try-on-option.rs:7:6
|
||||||
|
|
|
|
||||||
|
LL | fn foo() -> Result<u32, ()> {
|
||||||
|
| --------------- expected `()` because of this
|
||||||
|
LL | let x: Option<u32> = None;
|
||||||
LL | x?;
|
LL | x?;
|
||||||
| ^ the trait `std::convert::From<std::option::NoneError>` is not implemented for `()`
|
| ^ the trait `std::convert::From<std::option::NoneError>` is not implemented for `()`
|
||||||
|
|
|
|
||||||
|
Loading…
Reference in New Issue
Block a user