Skip to content

Commit ce43d6c

Browse files
Rollup merge of #150441 - fee1-dead-contrib:push-smqzpwrpvqll, r=estebank
do not suggest method call removal if it changes receiver type Fixes #149487, cc `@estebank`
2 parents 418beb4 + 998a0df commit ce43d6c

3 files changed

Lines changed: 62 additions & 11 deletions

File tree

compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4069,15 +4069,46 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
40694069
))
40704070
&& expr.span.hi() != rcvr.span.hi()
40714071
{
4072-
err.span_suggestion_verbose(
4073-
expr.span.with_lo(rcvr.span.hi()),
4074-
format!(
4075-
"consider removing this method call, as the receiver has type `{ty}` and \
4076-
`{pred}` trivially holds",
4077-
),
4078-
"",
4079-
Applicability::MaybeIncorrect,
4080-
);
4072+
let should_sugg = match tcx.hir_node(call_hir_id) {
4073+
Node::Expr(hir::Expr {
4074+
kind: hir::ExprKind::MethodCall(_, call_receiver, _, _),
4075+
..
4076+
}) if let Some((DefKind::AssocFn, did)) =
4077+
typeck_results.type_dependent_def(call_hir_id)
4078+
&& call_receiver.hir_id == arg_hir_id =>
4079+
{
4080+
// Avoid suggesting removing a method call if the argument is the receiver of the parent call and
4081+
// removing the receiver would make the method inaccessible. i.e. `x.a().b()`, suggesting removing
4082+
// `.a()` could change the type and make `.b()` unavailable.
4083+
if tcx.inherent_impl_of_assoc(did).is_some() {
4084+
// if we're calling an inherent impl method, just try to make sure that the receiver type stays the same.
4085+
Some(ty) == typeck_results.node_type_opt(arg_hir_id)
4086+
} else {
4087+
// we're calling a trait method, so we just check removing the method call still satisfies the trait.
4088+
let trait_id = tcx
4089+
.trait_of_assoc(did)
4090+
.unwrap_or_else(|| tcx.impl_trait_id(tcx.parent(did)));
4091+
let args = typeck_results.node_args(call_hir_id);
4092+
let tr = ty::TraitRef::from_assoc(tcx, trait_id, args)
4093+
.with_replaced_self_ty(tcx, ty);
4094+
self.type_implements_trait(tr.def_id, tr.args, param_env)
4095+
.must_apply_modulo_regions()
4096+
}
4097+
}
4098+
_ => true,
4099+
};
4100+
4101+
if should_sugg {
4102+
err.span_suggestion_verbose(
4103+
expr.span.with_lo(rcvr.span.hi()),
4104+
format!(
4105+
"consider removing this method call, as the receiver has type `{ty}` and \
4106+
`{pred}` trivially holds",
4107+
),
4108+
"",
4109+
Applicability::MaybeIncorrect,
4110+
);
4111+
}
40814112
}
40824113
if let hir::Expr { kind: hir::ExprKind::Block(block, _), .. } = expr {
40834114
let inner_expr = expr.peel_blocks();

tests/ui/trait-bounds/argument-with-unnecessary-method-call.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,11 @@ fn main() {
99
//~| HELP try using a fully qualified path to specify the expected types
1010
//~| HELP consider removing this method call, as the receiver has type `Bar` and `Bar: From<Bar>` trivially holds
1111
}
12+
13+
// regression test for https://github.com/rust-lang/rust/issues/149487.
14+
fn quux() {
15+
let mut tx_heights: std::collections::BTreeMap<(), Option<()>> = <_>::default();
16+
tx_heights.get(&()).unwrap_or_default();
17+
//~^ ERROR the trait bound `&Option<()>: Default` is not satisfied
18+
//~| HELP: the trait `Default` is implemented for `Option<T>`
19+
}

tests/ui/trait-bounds/argument-with-unnecessary-method-call.stderr

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,18 @@ LL - qux(Bar.into());
2323
LL + qux(Bar);
2424
|
2525

26-
error: aborting due to 1 previous error
26+
error[E0277]: the trait bound `&Option<()>: Default` is not satisfied
27+
--> $DIR/argument-with-unnecessary-method-call.rs:16:25
28+
|
29+
LL | tx_heights.get(&()).unwrap_or_default();
30+
| ^^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `&Option<()>`
31+
|
32+
help: the trait `Default` is implemented for `Option<T>`
33+
--> $SRC_DIR/core/src/option.rs:LL:COL
34+
note: required by a bound in `Option::<T>::unwrap_or_default`
35+
--> $SRC_DIR/core/src/option.rs:LL:COL
36+
37+
error: aborting due to 2 previous errors
2738

28-
For more information about this error, try `rustc --explain E0283`.
39+
Some errors have detailed explanations: E0277, E0283.
40+
For more information about an error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)