diff options
| author | Dylan DPC <dylan.dpc@gmail.com> | 2020-04-16 16:34:27 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-04-16 16:34:27 +0200 |
| commit | e4ec7965ef364e3860cb8d24a877d3e420f015b9 (patch) | |
| tree | 403b48010ee018f523ca07c1b60cfd07a6c30538 /src | |
| parent | 33500a2bbfec4482e0f149eafdeb9e111feeb5fc (diff) | |
| parent | fbc4168d809dae0408c2520ccfe585f564ad4a0b (diff) | |
| download | rust-e4ec7965ef364e3860cb8d24a877d3e420f015b9.tar.gz rust-e4ec7965ef364e3860cb8d24a877d3e420f015b9.zip | |
Rollup merge of #71141 - Duddino:master, r=estebank
Provide better compiler output when using `?` on `Option` in fn returning `Result` and vice-versa Fixes #71089
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc_trait_selection/traits/error_reporting/mod.rs | 23 | ||||
| -rw-r--r-- | src/test/ui/option-to-result.rs | 13 | ||||
| -rw-r--r-- | src/test/ui/option-to-result.stderr | 29 | ||||
| -rw-r--r-- | src/test/ui/try-on-option.stderr | 4 |
4 files changed, 68 insertions, 1 deletions
diff --git a/src/librustc_trait_selection/traits/error_reporting/mod.rs b/src/librustc_trait_selection/traits/error_reporting/mod.rs index fef7adf0224..904720125d3 100644 --- a/src/librustc_trait_selection/traits/error_reporting/mod.rs +++ b/src/librustc_trait_selection/traits/error_reporting/mod.rs @@ -292,7 +292,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { )), Some( "the question mark operation (`?`) implicitly performs a \ - conversion on the error value using the `From` trait" + conversion on the error value using the `From` trait" .to_owned(), ), ) @@ -312,6 +312,27 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { )) ); + let should_convert_option_to_result = + format!("{}", trait_ref.print_only_trait_path()) + .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, + ); + } + let explanation = if obligation.cause.code == ObligationCauseCode::MainFunctionType { "consider using `()`, or a `Result`".to_owned() diff --git a/src/test/ui/option-to-result.rs b/src/test/ui/option-to-result.rs new file mode 100644 index 00000000000..00e8b5244c5 --- /dev/null +++ b/src/test/ui/option-to-result.rs @@ -0,0 +1,13 @@ +fn main(){ } + +fn test_result() -> Result<(),()> { + let a:Option<()> = Some(()); + a?;//~ ERROR `?` couldn't convert the error + Ok(()) +} + +fn test_option() -> Option<i32>{ + let a:Result<i32, i32> = Ok(5); + a?;//~ ERROR `?` couldn't convert the error + Some(5) +} diff --git a/src/test/ui/option-to-result.stderr b/src/test/ui/option-to-result.stderr new file mode 100644 index 00000000000..f673ef7fc1e --- /dev/null +++ b/src/test/ui/option-to-result.stderr @@ -0,0 +1,29 @@ +error[E0277]: `?` couldn't convert the error to `()` + --> $DIR/option-to-result.rs:5:6 + | +LL | a?; + | ^ the trait `std::convert::From<std::option::NoneError>` is not implemented for `()` + | + = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait + = note: required by `std::convert::From::from` +help: consider converting the `Option<T>` into a `Result<T, _>` using `Option::ok_or` or `Option::ok_or_else` + | +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 | a?; + | ^ the trait `std::convert::From<i32>` is not implemented for `std::option::NoneError` + | + = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait + = note: required by `std::convert::From::from` +help: consider converting the `Result<T, _>` into an `Option<T>` using `Result::ok` + | +LL | a.ok()?; + | ^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/try-on-option.stderr b/src/test/ui/try-on-option.stderr index 07615b52a48..7a4bb75967b 100644 --- a/src/test/ui/try-on-option.stderr +++ b/src/test/ui/try-on-option.stderr @@ -6,6 +6,10 @@ LL | x?; | = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait = note: required by `std::convert::From::from` +help: consider converting the `Option<T>` into a `Result<T, _>` using `Option::ok_or` or `Option::ok_or_else` + | +LL | x.ok_or_else(|| /* error value */)?; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `std::ops::Try`) --> $DIR/try-on-option.rs:13:5 |
