Skip to content

Commit

Permalink
Detect when method call on argument could be removed to fulfill faile…
Browse files Browse the repository at this point in the history
…d 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 rust-lang#71252
  • Loading branch information
estebank committed Feb 14, 2024
1 parent eaff1af commit 9a1d514
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -3961,6 +3961,26 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for 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.skip_binder().with_self_ty(tcx, ty)
&& self
.evaluate_obligation_no_overflow(&Obligation::misc(
tcx, expr.span, body_id, param_env, pred,
))
.must_apply_modulo_regions()
{
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}` can be fulfilled",
),
"",
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 @@ -4096,7 +4116,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for 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>` can be fulfilled
|
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` can be fulfilled
|
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` can be fulfilled
|
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

0 comments on commit 9a1d514

Please sign in to comment.