Detect when method call on argument could be removed to fulfill failed trait bound
When encountering ```rust struct Foo; struct Bar; impl From<Bar> for Foo { fn from(_: Bar) -> Self { Foo } } fn qux(_: impl From<Bar>) {} fn main() { qux(Bar.into()); } ``` Suggest removing `.into()`: ``` error[E0283]: type annotations needed --> f100.rs:8:13 | 8 | qux(Bar.into()); | --- ^^^^ | | | required by a bound introduced by this call | = note: cannot satisfy `_: From<Bar>` note: required by a bound in `qux` --> f100.rs:6:16 | 6 | fn qux(_: impl From<Bar>) {} | ^^^^^^^^^ required by this bound in `qux` help: try using a fully qualified path to specify the expected types | 8 | qux(<Bar as Into<T>>::into(Bar)); | +++++++++++++++++++++++ ~ help: consider removing this method call, as the receiver has type `Bar` and `Bar: From<Bar>` can be fulfilled | 8 - qux(Bar.into()); 8 + qux(Bar); | ``` Fix #71252
This commit is contained in:
parent
0f806a9812
commit
9b3fcf9ad4
@ -3961,6 +3961,24 @@ fn note_function_argument_obligation(
|
|||||||
if let Node::Expr(expr) = tcx.hir_node(arg_hir_id)
|
if let Node::Expr(expr) = tcx.hir_node(arg_hir_id)
|
||||||
&& let Some(typeck_results) = &self.typeck_results
|
&& let Some(typeck_results) = &self.typeck_results
|
||||||
{
|
{
|
||||||
|
if let hir::Expr { kind: hir::ExprKind::MethodCall(_, rcvr, _, _), .. } = expr
|
||||||
|
&& let Some(ty) = typeck_results.node_type_opt(rcvr.hir_id)
|
||||||
|
&& let Some(failed_pred) = failed_pred.to_opt_poly_trait_pred()
|
||||||
|
&& let pred = failed_pred.map_bound(|pred| pred.with_self_ty(tcx, ty))
|
||||||
|
&& self.predicate_must_hold_modulo_regions(&Obligation::misc(
|
||||||
|
tcx, expr.span, body_id, param_env, pred,
|
||||||
|
))
|
||||||
|
{
|
||||||
|
err.span_suggestion_verbose(
|
||||||
|
expr.span.with_lo(rcvr.span.hi()),
|
||||||
|
format!(
|
||||||
|
"consider removing this method call, as the receiver has type `{ty}` and \
|
||||||
|
`{pred}` trivially holds",
|
||||||
|
),
|
||||||
|
"",
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
);
|
||||||
|
}
|
||||||
if let hir::Expr { kind: hir::ExprKind::Block(block, _), .. } = expr {
|
if let hir::Expr { kind: hir::ExprKind::Block(block, _), .. } = expr {
|
||||||
let inner_expr = expr.peel_blocks();
|
let inner_expr = expr.peel_blocks();
|
||||||
let ty = typeck_results
|
let ty = typeck_results
|
||||||
@ -4096,7 +4114,7 @@ fn note_function_argument_obligation(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Node::Expr(expr) = tcx.hir_node(call_hir_id) {
|
if let Node::Expr(expr) = call_node {
|
||||||
if let hir::ExprKind::Call(hir::Expr { span, .. }, _)
|
if let hir::ExprKind::Call(hir::Expr { span, .. }, _)
|
||||||
| hir::ExprKind::MethodCall(
|
| hir::ExprKind::MethodCall(
|
||||||
hir::PathSegment { ident: Ident { span, .. }, .. },
|
hir::PathSegment { ident: Ident { span, .. }, .. },
|
||||||
|
@ -8,6 +8,11 @@ LL | let mut f = File::open(path.to_str())?;
|
|||||||
|
|
|
|
||||||
note: required by a bound in `File::open`
|
note: required by a bound in `File::open`
|
||||||
--> $SRC_DIR/std/src/fs.rs:LL:COL
|
--> $SRC_DIR/std/src/fs.rs:LL:COL
|
||||||
|
help: consider removing this method call, as the receiver has type `&Path` and `&Path: AsRef<Path>` trivially holds
|
||||||
|
|
|
||||||
|
LL - let mut f = File::open(path.to_str())?;
|
||||||
|
LL + let mut f = File::open(path)?;
|
||||||
|
|
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
@ -11,6 +11,11 @@ note: required by a bound in `check_bound`
|
|||||||
|
|
|
|
||||||
LL | fn check_bound<T:Copy>(_: T) {}
|
LL | fn check_bound<T:Copy>(_: T) {}
|
||||||
| ^^^^ required by this bound in `check_bound`
|
| ^^^^ required by this bound in `check_bound`
|
||||||
|
help: consider removing this method call, as the receiver has type `&'static str` and `&'static str: Copy` trivially holds
|
||||||
|
|
|
||||||
|
LL - check_bound("nocopy".to_string());
|
||||||
|
LL + check_bound("nocopy");
|
||||||
|
|
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
@ -11,6 +11,11 @@ note: required by a bound in `f_copy`
|
|||||||
|
|
|
|
||||||
LL | fn f_copy<T: Copy>(t: T) {}
|
LL | fn f_copy<T: Copy>(t: T) {}
|
||||||
| ^^^^ required by this bound in `f_copy`
|
| ^^^^ required by this bound in `f_copy`
|
||||||
|
help: consider removing this method call, as the receiver has type `&'static str` and `&'static str: Copy` trivially holds
|
||||||
|
|
|
||||||
|
LL - f_copy("".to_string());
|
||||||
|
LL + f_copy("");
|
||||||
|
|
|
||||||
|
|
||||||
error[E0277]: the trait bound `S: Clone` is not satisfied
|
error[E0277]: the trait bound `S: Clone` is not satisfied
|
||||||
--> $DIR/issue-84973-blacklist.rs:16:13
|
--> $DIR/issue-84973-blacklist.rs:16:13
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
struct Foo;
|
||||||
|
struct Bar;
|
||||||
|
impl From<Bar> for Foo {
|
||||||
|
fn from(_: Bar) -> Self { Foo }
|
||||||
|
}
|
||||||
|
fn qux(_: impl From<Bar>) {}
|
||||||
|
fn main() {
|
||||||
|
qux(Bar.into()); //~ ERROR type annotations needed
|
||||||
|
//~| HELP try using a fully qualified path to specify the expected types
|
||||||
|
//~| HELP consider removing this method call, as the receiver has type `Bar` and `Bar: From<Bar>` trivially holds
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
error[E0283]: type annotations needed
|
||||||
|
--> $DIR/argument-with-unnecessary-method-call.rs:8:13
|
||||||
|
|
|
||||||
|
LL | qux(Bar.into());
|
||||||
|
| --- ^^^^
|
||||||
|
| |
|
||||||
|
| required by a bound introduced by this call
|
||||||
|
|
|
||||||
|
= note: cannot satisfy `_: From<Bar>`
|
||||||
|
note: required by a bound in `qux`
|
||||||
|
--> $DIR/argument-with-unnecessary-method-call.rs:6:16
|
||||||
|
|
|
||||||
|
LL | fn qux(_: impl From<Bar>) {}
|
||||||
|
| ^^^^^^^^^ required by this bound in `qux`
|
||||||
|
help: try using a fully qualified path to specify the expected types
|
||||||
|
|
|
||||||
|
LL | qux(<Bar as Into<T>>::into(Bar));
|
||||||
|
| +++++++++++++++++++++++ ~
|
||||||
|
help: consider removing this method call, as the receiver has type `Bar` and `Bar: From<Bar>` trivially holds
|
||||||
|
|
|
||||||
|
LL - qux(Bar.into());
|
||||||
|
LL + qux(Bar);
|
||||||
|
|
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0283`.
|
Loading…
Reference in New Issue
Block a user