diff options
| author | Dylan DPC <dylan.dpc@gmail.com> | 2020-04-27 03:26:13 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-04-27 03:26:13 +0200 |
| commit | c95bcbc9d5db498b572909bdcc56e684ceece68a (patch) | |
| tree | 75931a16e227fced8b9fde5491e8d2a14b71096e /src | |
| parent | 89aff5f33e1b28093e881e812b670672f724d8aa (diff) | |
| parent | be90f90810438eed6f0090acfb4d29a787a43c1e (diff) | |
| download | rust-c95bcbc9d5db498b572909bdcc56e684ceece68a.tar.gz rust-c95bcbc9d5db498b572909bdcc56e684ceece68a.zip | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc_trait_selection/traits/error_reporting/mod.rs | 38 | ||||
| -rw-r--r-- | src/librustc_trait_selection/traits/error_reporting/suggestions.rs | 13 | ||||
| -rw-r--r-- | src/test/ui/issues/issue-32709.stderr | 2 | ||||
| -rw-r--r-- | src/test/ui/option-to-result.stderr | 6 | ||||
| -rw-r--r-- | src/test/ui/try-on-option.stderr | 3 |
5 files changed, 48 insertions, 14 deletions
diff --git a/src/librustc_trait_selection/traits/error_reporting/mod.rs b/src/librustc_trait_selection/traits/error_reporting/mod.rs index fa9f1c9a7d9..35eb5d73ada 100644 --- a/src/librustc_trait_selection/traits/error_reporting/mod.rs +++ b/src/librustc_trait_selection/traits/error_reporting/mod.rs @@ -317,20 +317,30 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { .starts_with("std::convert::From<std::option::NoneError"); let should_convert_result_to_option = format!("{}", trait_ref) .starts_with("<std::option::NoneError as std::convert::From<"); - if is_try && is_from && should_convert_option_to_result { - err.span_suggestion_verbose( - span.shrink_to_lo(), - "consider converting the `Option<T>` into a `Result<T, _>` using `Option::ok_or` or `Option::ok_or_else`", - ".ok_or_else(|| /* error value */)".to_string(), - Applicability::HasPlaceholders, - ); - } else if is_try && is_from && should_convert_result_to_option { - err.span_suggestion_verbose( - span.shrink_to_lo(), - "consider converting the `Result<T, _>` into an `Option<T>` using `Result::ok`", - ".ok()".to_string(), - Applicability::MachineApplicable, - ); + if is_try && is_from { + if should_convert_option_to_result { + err.span_suggestion_verbose( + span.shrink_to_lo(), + "consider converting the `Option<T>` into a `Result<T, _>` \ + using `Option::ok_or` or `Option::ok_or_else`", + ".ok_or_else(|| /* error value */)".to_string(), + Applicability::HasPlaceholders, + ); + } else if should_convert_result_to_option { + err.span_suggestion_verbose( + span.shrink_to_lo(), + "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 = diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs index 19260f4d573..a927013e25f 100644 --- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs +++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs @@ -84,6 +84,8 @@ pub trait InferCtxtExt<'tcx> { trait_ref: &ty::Binder<ty::TraitRef<'tcx>>, ); + fn return_type_span(&self, obligation: &PredicateObligation<'tcx>) -> Option<Span>; + fn suggest_impl_trait( &self, 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 /// applicable and signal that the error has been expanded appropriately and needs to be /// emitted. diff --git a/src/test/ui/issues/issue-32709.stderr b/src/test/ui/issues/issue-32709.stderr index 04b8c3aa353..af272633f21 100644 --- a/src/test/ui/issues/issue-32709.stderr +++ b/src/test/ui/issues/issue-32709.stderr @@ -1,6 +1,8 @@ error[E0277]: `?` couldn't convert the error to `()` --> $DIR/issue-32709.rs:4:11 | +LL | fn a() -> Result<i32, ()> { + | --------------- expected `()` because of this LL | Err(5)?; | ^ the trait `std::convert::From<{integer}>` is not implemented for `()` | diff --git a/src/test/ui/option-to-result.stderr b/src/test/ui/option-to-result.stderr index f673ef7fc1e..5fa06778389 100644 --- a/src/test/ui/option-to-result.stderr +++ b/src/test/ui/option-to-result.stderr @@ -1,6 +1,9 @@ error[E0277]: `?` couldn't convert the error to `()` --> $DIR/option-to-result.rs:5:6 | +LL | fn test_result() -> Result<(),()> { + | ------------- expected `()` because of this +LL | let a:Option<()> = Some(()); LL | a?; | ^ 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` --> $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?; | ^ the trait `std::convert::From<i32>` is not implemented for `std::option::NoneError` | diff --git a/src/test/ui/try-on-option.stderr b/src/test/ui/try-on-option.stderr index 7a4bb75967b..33ca58bf7fe 100644 --- a/src/test/ui/try-on-option.stderr +++ b/src/test/ui/try-on-option.stderr @@ -1,6 +1,9 @@ error[E0277]: `?` couldn't convert the error to `()` --> $DIR/try-on-option.rs:7:6 | +LL | fn foo() -> Result<u32, ()> { + | --------------- expected `()` because of this +LL | let x: Option<u32> = None; LL | x?; | ^ the trait `std::convert::From<std::option::NoneError>` is not implemented for `()` | |
