diff options
| author | Esteban Küber <esteban@kuber.com.ar> | 2024-02-14 17:48:40 +0000 |
|---|---|---|
| committer | Esteban Küber <esteban@kuber.com.ar> | 2024-02-16 04:28:05 +0000 |
| commit | 9b3fcf9ad44faa6362be348ef233bbc81d128308 (patch) | |
| tree | f473d45832c661bd6d4f8d2a2949ee7fdca74ef3 /compiler | |
| parent | 0f806a9812b62c36bdab08d33c14cf2d3ecf4355 (diff) | |
| download | rust-9b3fcf9ad44faa6362be348ef233bbc81d128308.tar.gz rust-9b3fcf9ad44faa6362be348ef233bbc81d128308.zip | |
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
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs | 20 |
1 files changed, 19 insertions, 1 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 335e6ff2822..00672af52ea 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -3961,6 +3961,24 @@ 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.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 @@ -4096,7 +4114,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, .. }, .. }, |
