Skip to content

Commit

Permalink
Rollup merge of rust-lang#107633 - clubby789:option-string-coerce-fix…
Browse files Browse the repository at this point in the history
…, r=Nilstrieb

Fix suggestion for coercing Option<&String> to Option<&str>

Fixes rust-lang#107604

This also makes the diagnostic `MachineApplicable`, and runs `rustfix` to check we're not producing incorrect code.

``@rustbot`` label +A-diagnostics
  • Loading branch information
Dylan-DPC authored Feb 3, 2023
2 parents d6f0c51 + f874f67 commit c927027
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 13 deletions.
2 changes: 2 additions & 0 deletions compiler/rustc_error_messages/locales/en-US/hir_typeck.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -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`
13 changes: 9 additions & 4 deletions compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down
18 changes: 18 additions & 0 deletions tests/ui/typeck/issue-89856.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// run-rustfix

fn take_str_maybe(_: Option<&str>) { }
fn main() {
let string = String::from("Hello, world");

let option: Option<String> = 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]
}
14 changes: 12 additions & 2 deletions tests/ui/typeck/issue-89856.rs
Original file line number Diff line number Diff line change
@@ -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<String> = 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]
}
54 changes: 47 additions & 7 deletions tests/ui/typeck/issue-89856.stderr
Original file line number Diff line number Diff line change
@@ -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<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(_: 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`.

0 comments on commit c927027

Please sign in to comment.