From f874f6768caa8b59b99feffc708e868328129fd5 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Fri, 3 Feb 2023 11:10:24 +0000 Subject: [PATCH] Fix suggestion for coercing Option<&String> to Option<&str> --- .../locales/en-US/hir_typeck.ftl | 2 + .../src/fn_ctxt/suggestions.rs | 13 +++-- tests/ui/typeck/issue-89856.fixed | 18 +++++++ tests/ui/typeck/issue-89856.rs | 14 ++++- tests/ui/typeck/issue-89856.stderr | 54 ++++++++++++++++--- 5 files changed, 88 insertions(+), 13 deletions(-) create mode 100644 tests/ui/typeck/issue-89856.fixed diff --git a/compiler/rustc_error_messages/locales/en-US/hir_typeck.ftl b/compiler/rustc_error_messages/locales/en-US/hir_typeck.ftl index 0f13d29d0fcb6..05ac8db0db88f 100644 --- a/compiler/rustc_error_messages/locales/en-US/hir_typeck.ftl +++ b/compiler/rustc_error_messages/locales/en-US/hir_typeck.ftl @@ -61,3 +61,5 @@ hir_typeck_lang_start_incorrect_ret_ty = the return type of the `start` lang ite hir_typeck_help_set_edition_cargo = set `edition = "{$edition}"` in `Cargo.toml` hir_typeck_help_set_edition_standalone = pass `--edition {$edition}` to `rustc` hir_typeck_note_edition_guide = for more on editions, read https://doc.rust-lang.org/edition-guide + +hir_typeck_convert_to_str = try converting the passed type into a `&str` diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 6046e55c65c18..3f433a0928c55 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -3,7 +3,7 @@ use super::FnCtxt; use crate::errors::{AddReturnTypeSuggestion, ExpectedReturnTypeLabel}; use crate::method::probe::{IsSuggestion, Mode, ProbeScope}; use rustc_ast::util::parser::{ExprPrecedence, PREC_POSTFIX}; -use rustc_errors::{Applicability, Diagnostic, MultiSpan}; +use rustc_errors::{fluent, Applicability, Diagnostic, MultiSpan}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind}; use rustc_hir::lang_items::LangItem; @@ -414,11 +414,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let ty::Adt(adt, _) = peeled.kind() && Some(adt.did()) == self.tcx.lang_items().string() { + let sugg = if ref_cnt == 0 { + ".as_deref()" + } else { + ".map(|x| x.as_str())" + }; err.span_suggestion_verbose( expr.span.shrink_to_hi(), - "try converting the passed type into a `&str`", - format!(".map(|x| &*{}x)", "*".repeat(ref_cnt)), - Applicability::MaybeIncorrect, + fluent::hir_typeck_convert_to_str, + sugg, + Applicability::MachineApplicable, ); return true; } diff --git a/tests/ui/typeck/issue-89856.fixed b/tests/ui/typeck/issue-89856.fixed new file mode 100644 index 0000000000000..3e1a006efa069 --- /dev/null +++ b/tests/ui/typeck/issue-89856.fixed @@ -0,0 +1,18 @@ +// run-rustfix + +fn take_str_maybe(_: Option<&str>) { } +fn main() { + let string = String::from("Hello, world"); + + let option: Option = Some(string.clone()); + take_str_maybe(option.as_deref()); + //~^ ERROR: mismatched types [E0308] + + let option_ref = Some(&string); + take_str_maybe(option_ref.map(|x| x.as_str())); + //~^ ERROR: mismatched types [E0308] + + let option_ref_ref = option_ref.as_ref(); + take_str_maybe(option_ref_ref.map(|x| x.as_str())); + //~^ ERROR: mismatched types [E0308] +} diff --git a/tests/ui/typeck/issue-89856.rs b/tests/ui/typeck/issue-89856.rs index b021e349e358c..cfe6e19b303f3 100644 --- a/tests/ui/typeck/issue-89856.rs +++ b/tests/ui/typeck/issue-89856.rs @@ -1,8 +1,18 @@ -fn take_str_maybe(x: Option<&str>) -> Option<&str> { None } +// run-rustfix +fn take_str_maybe(_: Option<&str>) { } fn main() { let string = String::from("Hello, world"); - let option = Some(&string); + + let option: Option = Some(string.clone()); take_str_maybe(option); //~^ ERROR: mismatched types [E0308] + + let option_ref = Some(&string); + take_str_maybe(option_ref); + //~^ ERROR: mismatched types [E0308] + + let option_ref_ref = option_ref.as_ref(); + take_str_maybe(option_ref_ref); + //~^ ERROR: mismatched types [E0308] } diff --git a/tests/ui/typeck/issue-89856.stderr b/tests/ui/typeck/issue-89856.stderr index 6b9cbe52c2553..bd76f17246821 100644 --- a/tests/ui/typeck/issue-89856.stderr +++ b/tests/ui/typeck/issue-89856.stderr @@ -1,23 +1,63 @@ error[E0308]: mismatched types - --> $DIR/issue-89856.rs:6:20 + --> $DIR/issue-89856.rs:8:20 | LL | take_str_maybe(option); - | -------------- ^^^^^^ expected `Option<&str>`, found `Option<&String>` + | -------------- ^^^^^^ expected `Option<&str>`, found `Option` + | | + | arguments to this function are incorrect + | + = note: expected enum `Option<&str>` + found enum `Option` +note: function defined here + --> $DIR/issue-89856.rs:3:4 + | +LL | fn take_str_maybe(_: Option<&str>) { } + | ^^^^^^^^^^^^^^ --------------- +help: try converting the passed type into a `&str` + | +LL | take_str_maybe(option.as_deref()); + | +++++++++++ + +error[E0308]: mismatched types + --> $DIR/issue-89856.rs:12:20 + | +LL | take_str_maybe(option_ref); + | -------------- ^^^^^^^^^^ expected `Option<&str>`, found `Option<&String>` | | | arguments to this function are incorrect | = note: expected enum `Option<&str>` found enum `Option<&String>` note: function defined here - --> $DIR/issue-89856.rs:1:4 + --> $DIR/issue-89856.rs:3:4 + | +LL | fn take_str_maybe(_: Option<&str>) { } + | ^^^^^^^^^^^^^^ --------------- +help: try converting the passed type into a `&str` + | +LL | take_str_maybe(option_ref.map(|x| x.as_str())); + | ++++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/issue-89856.rs:16:20 + | +LL | take_str_maybe(option_ref_ref); + | -------------- ^^^^^^^^^^^^^^ expected `Option<&str>`, found `Option<&&String>` + | | + | arguments to this function are incorrect + | + = note: expected enum `Option<&str>` + found enum `Option<&&String>` +note: function defined here + --> $DIR/issue-89856.rs:3:4 | -LL | fn take_str_maybe(x: Option<&str>) -> Option<&str> { None } +LL | fn take_str_maybe(_: Option<&str>) { } | ^^^^^^^^^^^^^^ --------------- help: try converting the passed type into a `&str` | -LL | take_str_maybe(option.map(|x| &**x)); - | ++++++++++++++ +LL | take_str_maybe(option_ref_ref.map(|x| x.as_str())); + | ++++++++++++++++++++ -error: aborting due to previous error +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0308`.