Skip to content

Commit 934cb10

Browse files
authored
Rollup merge of #145191 - dianne:fix-borrow-suggestion-args, r=compiler-errors
`suggest_borrow_generic_arg`: use the correct generic args The suggestion now gets calls' generic arguments from the callee's type to handle cases where the callee isn't an identifier expression. Fixes #145164.
2 parents 94b344d + a70a312 commit 934cb10

File tree

3 files changed

+53
-7
lines changed

3 files changed

+53
-7
lines changed

compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -410,18 +410,18 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
410410
}
411411
let typeck = self.infcx.tcx.typeck(self.mir_def_id());
412412
let parent = self.infcx.tcx.parent_hir_node(expr.hir_id);
413-
let (def_id, call_id, args, offset) = if let hir::Node::Expr(parent_expr) = parent
413+
let (def_id, args, offset) = if let hir::Node::Expr(parent_expr) = parent
414414
&& let hir::ExprKind::MethodCall(_, _, args, _) = parent_expr.kind
415415
{
416416
let def_id = typeck.type_dependent_def_id(parent_expr.hir_id);
417-
(def_id, Some(parent_expr.hir_id), args, 1)
417+
(def_id, args, 1)
418418
} else if let hir::Node::Expr(parent_expr) = parent
419419
&& let hir::ExprKind::Call(call, args) = parent_expr.kind
420420
&& let ty::FnDef(def_id, _) = typeck.node_type(call.hir_id).kind()
421421
{
422-
(Some(*def_id), Some(call.hir_id), args, 0)
422+
(Some(*def_id), args, 0)
423423
} else {
424-
(None, None, &[][..], 0)
424+
(None, &[][..], 0)
425425
};
426426
let ty = place.ty(self.body, self.infcx.tcx).ty;
427427

@@ -459,11 +459,12 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
459459
// If the moved place is used generically by the callee and a reference to it
460460
// would still satisfy any bounds on its type, suggest borrowing.
461461
if let Some(&param) = arg_param
462-
&& let Some(generic_args) = call_id.and_then(|id| typeck.node_args_opt(id))
462+
&& let hir::Node::Expr(call_expr) = parent
463463
&& let Some(ref_mutability) = self.suggest_borrow_generic_arg(
464464
err,
465+
typeck,
466+
call_expr,
465467
def_id,
466-
generic_args,
467468
param,
468469
moved_place,
469470
pos + offset,
@@ -627,8 +628,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
627628
fn suggest_borrow_generic_arg(
628629
&self,
629630
err: &mut Diag<'_>,
631+
typeck: &ty::TypeckResults<'tcx>,
632+
call_expr: &hir::Expr<'tcx>,
630633
callee_did: DefId,
631-
generic_args: ty::GenericArgsRef<'tcx>,
632634
param: ty::ParamTy,
633635
moved_place: PlaceRef<'tcx>,
634636
moved_arg_pos: usize,
@@ -639,6 +641,19 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
639641
let sig = tcx.fn_sig(callee_did).instantiate_identity().skip_binder();
640642
let clauses = tcx.predicates_of(callee_did);
641643

644+
let generic_args = match call_expr.kind {
645+
// For method calls, generic arguments are attached to the call node.
646+
hir::ExprKind::MethodCall(..) => typeck.node_args_opt(call_expr.hir_id)?,
647+
// For normal calls, generic arguments are in the callee's type.
648+
// This diagnostic is only run for `FnDef` callees.
649+
hir::ExprKind::Call(callee, _)
650+
if let &ty::FnDef(_, args) = typeck.node_type(callee.hir_id).kind() =>
651+
{
652+
args
653+
}
654+
_ => return None,
655+
};
656+
642657
// First, is there at least one method on one of `param`'s trait bounds?
643658
// This keeps us from suggesting borrowing the argument to `mem::drop`, e.g.
644659
if !clauses.instantiate_identity(tcx).predicates.iter().any(|clause| {
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//! Regression test for #145164: For normal calls, make sure the suggestion to borrow generic inputs
2+
//! uses the generic args from the callee's type rather than those attached to the callee's HIR
3+
//! node. In cases where the callee isn't an identifier expression, its HIR node won't have its
4+
//! generic arguments attached, which could lead to ICE when it had other generic args. In this
5+
//! case, the callee expression is `run.clone()`, to which `clone`'s generic arguments are attached.
6+
7+
fn main() {
8+
let value = String::new();
9+
run.clone()(value, ());
10+
run(value, ());
11+
//~^ ERROR use of moved value: `value`
12+
}
13+
fn run<F, T: Clone>(value: T, f: F) {}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
error[E0382]: use of moved value: `value`
2+
--> $DIR/use-correct-generic-args-in-borrow-suggest.rs:10:9
3+
|
4+
LL | let value = String::new();
5+
| ----- move occurs because `value` has type `String`, which does not implement the `Copy` trait
6+
LL | run.clone()(value, ());
7+
| ----- value moved here
8+
LL | run(value, ());
9+
| ^^^^^ value used here after move
10+
|
11+
help: consider borrowing `value`
12+
|
13+
LL | run.clone()(&value, ());
14+
| +
15+
16+
error: aborting due to 1 previous error
17+
18+
For more information about this error, try `rustc --explain E0382`.

0 commit comments

Comments
 (0)