More fix on mismatched type suggestion for shorthand fields
This commit is contained in:
parent
9386e14401
commit
3a4edf0a7f
@ -626,7 +626,7 @@ pub struct SuggestConvertViaMethod<'tcx> {
|
|||||||
pub span: Span,
|
pub span: Span,
|
||||||
#[suggestion_part(code = "")]
|
#[suggestion_part(code = "")]
|
||||||
pub borrow_removal_span: Option<Span>,
|
pub borrow_removal_span: Option<Span>,
|
||||||
pub sugg: &'static str,
|
pub sugg: String,
|
||||||
pub expected: Ty<'tcx>,
|
pub expected: Ty<'tcx>,
|
||||||
pub found: Ty<'tcx>,
|
pub found: Ty<'tcx>,
|
||||||
}
|
}
|
||||||
|
@ -442,12 +442,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
expected,
|
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`,
|
// 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.
|
// 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 {
|
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 {
|
err.subdiagnostic(errors::SuggestConvertViaMethod {
|
||||||
span: expr.span.shrink_to_hi(),
|
span: expr.span.shrink_to_hi(),
|
||||||
sugg: ".as_ref()",
|
sugg,
|
||||||
expected,
|
expected,
|
||||||
found,
|
found,
|
||||||
borrow_removal_span,
|
borrow_removal_span,
|
||||||
@ -458,9 +468,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
&& self.can_eq(self.param_env, deref_ty, peeled)
|
&& self.can_eq(self.param_env, deref_ty, peeled)
|
||||||
&& error_tys_equate_as_ref
|
&& error_tys_equate_as_ref
|
||||||
{
|
{
|
||||||
|
let sugg = prefix_wrap(".as_deref()");
|
||||||
err.subdiagnostic(errors::SuggestConvertViaMethod {
|
err.subdiagnostic(errors::SuggestConvertViaMethod {
|
||||||
span: expr.span.shrink_to_hi(),
|
span: expr.span.shrink_to_hi(),
|
||||||
sugg: ".as_deref()",
|
sugg,
|
||||||
expected,
|
expected,
|
||||||
found,
|
found,
|
||||||
borrow_removal_span,
|
borrow_removal_span,
|
||||||
@ -474,10 +485,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
self.can_eq(self.param_env, found, expected)
|
self.can_eq(self.param_env, found, expected)
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
|
let sugg = prefix_wrap(".map(|x| x.as_str())");
|
||||||
err.span_suggestion_verbose(
|
err.span_suggestion_verbose(
|
||||||
expr.span.shrink_to_hi(),
|
expr.span.shrink_to_hi(),
|
||||||
fluent::hir_typeck_convert_to_str,
|
fluent::hir_typeck_convert_to_str,
|
||||||
".map(|x| x.as_str())",
|
sugg,
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
);
|
);
|
||||||
return true;
|
return true;
|
||||||
@ -628,12 +640,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
err.help("use `Box::pin`");
|
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(
|
err.multipart_suggestion(
|
||||||
"you need to pin and box this expression",
|
"you need to pin and box this expression",
|
||||||
vec![
|
suggestion,
|
||||||
(expr.span.shrink_to_lo(), "Box::pin(".to_string()),
|
|
||||||
(expr.span.shrink_to_hi(), ")".to_string()),
|
|
||||||
],
|
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1214,7 +1234,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
span = parent_callsite;
|
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())]
|
vec![(span.shrink_to_hi(), ".into()".to_owned())]
|
||||||
} else {
|
} else {
|
||||||
vec![
|
vec![
|
||||||
@ -1222,6 +1242,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
(span.shrink_to_hi(), ").into()".to_owned()),
|
(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(
|
diag.multipart_suggestion(
|
||||||
format!("call `Into::into` on this expression to convert `{expr_ty}` into `{expected_ty}`"),
|
format!("call `Into::into` on this expression to convert `{expr_ty}` into `{expected_ty}`"),
|
||||||
sugg,
|
sugg,
|
||||||
|
@ -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() {}
|
@ -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() {}
|
@ -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`.
|
Loading…
x
Reference in New Issue
Block a user