Rollup merge of #118413 - chenyukang:yukang-fix-118145-unwrap-for-shorthand, r=compiler-errors

Fix the issue of suggesting unwrap/expect for shorthand field

Fixes #118145
This commit is contained in:
Matthias Krüger 2023-11-29 04:23:30 +01:00 committed by GitHub
commit 872753895f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 341 additions and 9 deletions

View File

@ -626,7 +626,7 @@ pub struct SuggestConvertViaMethod<'tcx> {
pub span: Span,
#[suggestion_part(code = "")]
pub borrow_removal_span: Option<Span>,
pub sugg: &'static str,
pub sugg: String,
pub expected: Ty<'tcx>,
pub found: Ty<'tcx>,
}

View File

@ -442,12 +442,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expected,
)
});
let prefix_wrap = |sugg: &str| {
if let Some(name) = self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
format!(": {}{}", name, sugg)
} else {
sugg.to_string()
}
};
// FIXME: This could/should be extended to suggest `as_mut` and `as_deref_mut`,
// but those checks need to be a bit more delicate and the benefit is diminishing.
if self.can_eq(self.param_env, found_ty_inner, peeled) && error_tys_equate_as_ref {
let sugg = prefix_wrap(".as_ref()");
err.subdiagnostic(errors::SuggestConvertViaMethod {
span: expr.span.shrink_to_hi(),
sugg: ".as_ref()",
sugg,
expected,
found,
borrow_removal_span,
@ -458,9 +468,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&& self.can_eq(self.param_env, deref_ty, peeled)
&& error_tys_equate_as_ref
{
let sugg = prefix_wrap(".as_deref()");
err.subdiagnostic(errors::SuggestConvertViaMethod {
span: expr.span.shrink_to_hi(),
sugg: ".as_deref()",
sugg,
expected,
found,
borrow_removal_span,
@ -474,10 +485,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.can_eq(self.param_env, found, expected)
})
{
let sugg = prefix_wrap(".map(|x| x.as_str())");
err.span_suggestion_verbose(
expr.span.shrink_to_hi(),
fluent::hir_typeck_convert_to_str,
".map(|x| x.as_str())",
sugg,
Applicability::MachineApplicable,
);
return true;
@ -628,12 +640,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
err.help("use `Box::pin`");
}
_ => {
let prefix = if let Some(name) =
self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr)
{
format!("{}: ", name)
} else {
String::new()
};
let suggestion = vec![
(expr.span.shrink_to_lo(), format!("{prefix}Box::pin(")),
(expr.span.shrink_to_hi(), ")".to_string()),
];
err.multipart_suggestion(
"you need to pin and box this expression",
vec![
(expr.span.shrink_to_lo(), "Box::pin(".to_string()),
(expr.span.shrink_to_hi(), ")".to_string()),
],
suggestion,
Applicability::MaybeIncorrect,
);
}
@ -1214,7 +1234,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
span = parent_callsite;
}
let sugg = if expr.precedence().order() >= PREC_POSTFIX {
let mut sugg = if expr.precedence().order() >= PREC_POSTFIX {
vec![(span.shrink_to_hi(), ".into()".to_owned())]
} else {
vec![
@ -1222,6 +1242,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
(span.shrink_to_hi(), ").into()".to_owned()),
]
};
if let Some(name) = self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
sugg.insert(0, (expr.span.shrink_to_lo(), format!("{}: ", name)));
}
diag.multipart_suggestion(
format!("call `Into::into` on this expression to convert `{expr_ty}` into `{expected_ty}`"),
sugg,
@ -1811,6 +1834,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
".expect(\"REASON\")",
)
};
let sugg = match self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
Some(ident) => format!(": {ident}{sugg}"),
None => sugg.to_string(),
};
err.span_suggestion_verbose(
expr.span.shrink_to_hi(),
msg,

View File

@ -0,0 +1,20 @@
// run-rustfix
#![allow(unused, dead_code)]
#[derive(Clone, Copy)]
struct Stuff {
count: i32,
}
struct Error;
fn demo() -> Result<Stuff, Error> {
let count = Ok(1);
Ok(Stuff { count: count? }) //~ ERROR mismatched types
}
fn demo_unwrap() -> Stuff {
let count = Some(1);
Stuff { count: count.expect("REASON") } //~ ERROR mismatched types
}
fn main() {}

View File

@ -0,0 +1,20 @@
// run-rustfix
#![allow(unused, dead_code)]
#[derive(Clone, Copy)]
struct Stuff {
count: i32,
}
struct Error;
fn demo() -> Result<Stuff, Error> {
let count = Ok(1);
Ok(Stuff { count }) //~ ERROR mismatched types
}
fn demo_unwrap() -> Stuff {
let count = Some(1);
Stuff { count } //~ ERROR mismatched types
}
fn main() {}

View File

@ -0,0 +1,29 @@
error[E0308]: mismatched types
--> $DIR/issue-118145-unwrap-for-shorthand.rs:12:16
|
LL | Ok(Stuff { count })
| ^^^^^ expected `i32`, found `Result<{integer}, _>`
|
= note: expected type `i32`
found enum `Result<{integer}, _>`
help: use the `?` operator to extract the `Result<{integer}, _>` value, propagating a `Result::Err` value to the caller
|
LL | Ok(Stuff { count: count? })
| ++++++++
error[E0308]: mismatched types
--> $DIR/issue-118145-unwrap-for-shorthand.rs:17:13
|
LL | Stuff { count }
| ^^^^^ expected `i32`, found `Option<{integer}>`
|
= note: expected type `i32`
found enum `Option<{integer}>`
help: consider using `Option::expect` to unwrap the `Option<{integer}>` value, panicking if the value is an `Option::None`
|
LL | Stuff { count: count.expect("REASON") }
| ++++++++++++++++++++++++
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0308`.

View File

@ -0,0 +1,77 @@
// run-rustfix
// edition:2021
#![allow(dead_code)]
#![allow(unused_variables)]
use std::future::Future;
use std::pin::Pin;
fn test1() {
let string = String::from("Hello, world");
struct Demo<'a> {
option: Option<&'a str>,
}
let option: Option<String> = Some(string.clone());
let s = Demo { option: option.as_deref() }; //~ ERROR mismatched types
}
fn test2() {
let string = String::from("Hello, world");
struct Demo<'a> {
option_ref: Option<&'a str>,
}
let option_ref = Some(&string);
let s = Demo { option_ref: option_ref.map(|x| x.as_str()) }; //~ ERROR mismatched types
}
fn test3() {
let string = String::from("Hello, world");
struct Demo<'a> {
option_ref_ref: Option<&'a str>,
}
let option_ref = Some(&string);
let option_ref_ref = option_ref.as_ref();
let s = Demo { option_ref_ref: option_ref_ref.map(|x| x.as_str()) }; //~ ERROR mismatched types
}
fn test4() {
let a = 1;
struct Demo {
a: String,
}
let s = Demo { a: a.to_string() }; //~ ERROR mismatched types
}
type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
fn test5() {
let a = async { 42 };
struct Demo {
a: BoxFuture<'static, i32>,
}
let s = Demo { a: Box::pin(a) }; //~ ERROR mismatched types
}
fn test6() {
struct A;
struct B;
impl From<B> for A {
fn from(_: B) -> Self {
A
}
}
struct Demo {
a: A,
}
let a = B;
let s = Demo { a: a.into() }; //~ ERROR mismatched types
}
fn main() {}

View File

@ -0,0 +1,77 @@
// run-rustfix
// edition:2021
#![allow(dead_code)]
#![allow(unused_variables)]
use std::future::Future;
use std::pin::Pin;
fn test1() {
let string = String::from("Hello, world");
struct Demo<'a> {
option: Option<&'a str>,
}
let option: Option<String> = Some(string.clone());
let s = Demo { option }; //~ ERROR mismatched types
}
fn test2() {
let string = String::from("Hello, world");
struct Demo<'a> {
option_ref: Option<&'a str>,
}
let option_ref = Some(&string);
let s = Demo { option_ref }; //~ ERROR mismatched types
}
fn test3() {
let string = String::from("Hello, world");
struct Demo<'a> {
option_ref_ref: Option<&'a str>,
}
let option_ref = Some(&string);
let option_ref_ref = option_ref.as_ref();
let s = Demo { option_ref_ref }; //~ ERROR mismatched types
}
fn test4() {
let a = 1;
struct Demo {
a: String,
}
let s = Demo { a }; //~ ERROR mismatched types
}
type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
fn test5() {
let a = async { 42 };
struct Demo {
a: BoxFuture<'static, i32>,
}
let s = Demo { a }; //~ ERROR mismatched types
}
fn test6() {
struct A;
struct B;
impl From<B> for A {
fn from(_: B) -> Self {
A
}
}
struct Demo {
a: A,
}
let a = B;
let s = Demo { a }; //~ ERROR mismatched types
}
fn main() {}

View File

@ -0,0 +1,80 @@
error[E0308]: mismatched types
--> $DIR/mismatch-sugg-for-shorthand-field.rs:16:20
|
LL | let s = Demo { option };
| ^^^^^^ expected `Option<&str>`, found `Option<String>`
|
= note: expected enum `Option<&str>`
found enum `Option<String>`
help: try using `: option.as_deref()` to convert `Option<String>` to `Option<&str>`
|
LL | let s = Demo { option: option.as_deref() };
| +++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/mismatch-sugg-for-shorthand-field.rs:27:20
|
LL | let s = Demo { option_ref };
| ^^^^^^^^^^ expected `Option<&str>`, found `Option<&String>`
|
= note: expected enum `Option<&str>`
found enum `Option<&String>`
help: try converting the passed type into a `&str`
|
LL | let s = Demo { option_ref: option_ref.map(|x| x.as_str()) };
| ++++++++++++++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/mismatch-sugg-for-shorthand-field.rs:40:20
|
LL | let s = Demo { option_ref_ref };
| ^^^^^^^^^^^^^^ expected `Option<&str>`, found `Option<&&String>`
|
= note: expected enum `Option<&str>`
found enum `Option<&&String>`
help: try converting the passed type into a `&str`
|
LL | let s = Demo { option_ref_ref: option_ref_ref.map(|x| x.as_str()) };
| ++++++++++++++++++++++++++++++++++++
error[E0308]: mismatched types
--> $DIR/mismatch-sugg-for-shorthand-field.rs:48:20
|
LL | let s = Demo { a };
| ^ expected `String`, found integer
|
help: try using a conversion method
|
LL | let s = Demo { a: a.to_string() };
| ++ ++++++++++++
error[E0308]: mismatched types
--> $DIR/mismatch-sugg-for-shorthand-field.rs:57:20
|
LL | let a = async { 42 };
| ------------ the found `async` block
...
LL | let s = Demo { a };
| ^ expected `Pin<Box<...>>`, found `async` block
|
= note: expected struct `Pin<Box<(dyn Future<Output = i32> + Send + 'static)>>`
found `async` block `{async block@$DIR/mismatch-sugg-for-shorthand-field.rs:53:13: 53:25}`
help: you need to pin and box this expression
|
LL | let s = Demo { a: Box::pin(a) };
| ++++++++++++ +
error[E0308]: mismatched types
--> $DIR/mismatch-sugg-for-shorthand-field.rs:74:20
|
LL | let s = Demo { a };
| ^ expected `A`, found `B`
|
help: call `Into::into` on this expression to convert `B` into `A`
|
LL | let s = Demo { a: a.into() };
| ++ +++++++
error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0308`.