Skip to content

Commit

Permalink
Rollup merge of rust-lang#121100 - estebank:issue-71252, r=compiler-e…
Browse files Browse the repository at this point in the history
…rrors

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>` trivially holds
  |
8 -     qux(Bar.into());
8 +     qux(Bar);
  |
```

Fix rust-lang#71252
  • Loading branch information
CKingX authored Feb 18, 2024
2 parents 3aff0b0 + 9b3fcf9 commit 72997ad
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -3689,6 +3689,24 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
if let Node::Expr(expr) = tcx.hir_node(arg_hir_id)
&& 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 {
let inner_expr = expr.peel_blocks();
let ty = typeck_results
Expand Down Expand Up @@ -3824,7 +3842,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
}
}

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, .. }, _)
| hir::ExprKind::MethodCall(
hir::PathSegment { ident: Ident { span, .. }, .. },
Expand Down
5 changes: 5 additions & 0 deletions tests/ui/async-await/issue-72442.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ LL | let mut f = File::open(path.to_str())?;
|
note: required by a bound in `File::open`
--> $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

Expand Down
5 changes: 5 additions & 0 deletions tests/ui/error-should-say-copy-not-pod.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ note: required by a bound in `check_bound`
|
LL | fn check_bound<T:Copy>(_: T) {}
| ^^^^ 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

Expand Down
5 changes: 5 additions & 0 deletions tests/ui/suggestions/issue-84973-blacklist.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ note: required by a bound in `f_copy`
|
LL | fn f_copy<T: Copy>(t: T) {}
| ^^^^ 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
--> $DIR/issue-84973-blacklist.rs:16:13
Expand Down
11 changes: 11 additions & 0 deletions tests/ui/trait-bounds/argument-with-unnecessary-method-call.rs
Original file line number Diff line number Diff line change
@@ -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
}
27 changes: 27 additions & 0 deletions tests/ui/trait-bounds/argument-with-unnecessary-method-call.stderr
Original file line number Diff line number Diff line change
@@ -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`.

0 comments on commit 72997ad

Please sign in to comment.