Skip to content

Commit fc4f71d

Browse files
authored
Rollup merge of #133130 - dianne:fix-133118, r=compiler-errors
`suggest_borrow_generic_arg`: instantiate clauses properly This simplifies and fixes the way `suggest_borrow_generic_arg` instantiates callees' predicates when testing them to see if a moved argument can instead be borrowed. Previously, it would ICE if the moved argument's type included a region variable, since it was getting passed to a call of `EarlyBinder::instantiate`. This makes the instantiation much more straightforward, which also fixes the ICE. Fixes #133118 This also modifies `tests/ui/moves/moved-value-on-as-ref-arg.rs` to have more useful bounds on the tests for suggestions to borrow `Borrow` and `BorrowMut` arguments. With its old tautological `T: BorrowMut<T>` bound, this fix would make it suggest a shared borrow for that argument.
2 parents c68fef9 + 546ba3d commit fc4f71d

File tree

5 files changed

+60
-20
lines changed

5 files changed

+60
-20
lines changed

compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

+10-16
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use rustc_middle::mir::{
2727
};
2828
use rustc_middle::ty::print::PrintTraitRefExt as _;
2929
use rustc_middle::ty::{
30-
self, ClauseKind, PredicateKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor, Upcast,
30+
self, PredicateKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor, Upcast,
3131
suggest_constraining_type_params,
3232
};
3333
use rustc_middle::util::CallKind;
@@ -649,11 +649,11 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
649649
) -> Option<ty::Mutability> {
650650
let tcx = self.infcx.tcx;
651651
let sig = tcx.fn_sig(callee_did).instantiate_identity().skip_binder();
652-
let clauses = tcx.predicates_of(callee_did).instantiate_identity(self.infcx.tcx).predicates;
652+
let clauses = tcx.predicates_of(callee_did);
653653

654654
// First, is there at least one method on one of `param`'s trait bounds?
655655
// This keeps us from suggesting borrowing the argument to `mem::drop`, e.g.
656-
if !clauses.iter().any(|clause| {
656+
if !clauses.instantiate_identity(tcx).predicates.iter().any(|clause| {
657657
clause.as_trait_clause().is_some_and(|tc| {
658658
tc.self_ty().skip_binder().is_param(param.index)
659659
&& tc.polarity() == ty::PredicatePolarity::Positive
@@ -700,23 +700,17 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
700700
return false;
701701
}
702702

703-
// Test the callee's predicates, substituting a reference in for the self ty
704-
// in bounds on `param`.
705-
clauses.iter().all(|&clause| {
706-
let clause_for_ref = clause.kind().map_bound(|kind| match kind {
707-
ClauseKind::Trait(c) if c.self_ty().is_param(param.index) => {
708-
ClauseKind::Trait(c.with_self_ty(tcx, ref_ty))
709-
}
710-
ClauseKind::Projection(c) if c.self_ty().is_param(param.index) => {
711-
ClauseKind::Projection(c.with_self_ty(tcx, ref_ty))
712-
}
713-
_ => kind,
714-
});
703+
// Test the callee's predicates, substituting in `ref_ty` for the moved argument type.
704+
clauses.instantiate(tcx, new_args).predicates.iter().all(|&(mut clause)| {
705+
// Normalize before testing to see through type aliases and projections.
706+
if let Ok(normalized) = tcx.try_normalize_erasing_regions(self.param_env, clause) {
707+
clause = normalized;
708+
}
715709
self.infcx.predicate_must_hold_modulo_regions(&Obligation::new(
716710
tcx,
717711
ObligationCause::dummy(),
718712
self.param_env,
719-
ty::EarlyBinder::bind(clause_for_ref).instantiate(tcx, generic_args),
713+
clause,
720714
))
721715
})
722716
}) {

tests/ui/moves/moved-value-on-as-ref-arg.fixed

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ impl AsMut<Bar> for Bar {
1818

1919
fn foo<T: AsRef<Bar>>(_: T) {}
2020
fn qux<T: AsMut<Bar>>(_: T) {}
21-
fn bat<T: Borrow<T>>(_: T) {}
22-
fn baz<T: BorrowMut<T>>(_: T) {}
21+
fn bat<T: Borrow<Bar>>(_: T) {}
22+
fn baz<T: BorrowMut<Bar>>(_: T) {}
2323

2424
pub fn main() {
2525
let bar = Bar;

tests/ui/moves/moved-value-on-as-ref-arg.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ impl AsMut<Bar> for Bar {
1818

1919
fn foo<T: AsRef<Bar>>(_: T) {}
2020
fn qux<T: AsMut<Bar>>(_: T) {}
21-
fn bat<T: Borrow<T>>(_: T) {}
22-
fn baz<T: BorrowMut<T>>(_: T) {}
21+
fn bat<T: Borrow<Bar>>(_: T) {}
22+
fn baz<T: BorrowMut<Bar>>(_: T) {}
2323

2424
pub fn main() {
2525
let bar = Bar;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//! regression test for #133118
2+
3+
pub trait Alpha {
4+
fn y(self) -> usize;
5+
}
6+
7+
pub trait Beta {
8+
type Gamma;
9+
fn gamma(&self) -> Self::Gamma;
10+
}
11+
12+
pub fn a<T: Alpha>(_x: T) -> usize {
13+
todo!();
14+
}
15+
16+
pub fn x<B>(beta: &B) -> usize
17+
where
18+
for<'a> &'a B: Beta,
19+
for<'a> <&'a B as Beta>::Gamma: Alpha,
20+
{
21+
let g1 = beta.gamma();
22+
a(g1) + a(g1) //~ ERROR use of moved value: `g1` [E0382]
23+
}
24+
25+
pub fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
error[E0382]: use of moved value: `g1`
2+
--> $DIR/region-var-in-moved-ty-issue-133118.rs:22:15
3+
|
4+
LL | let g1 = beta.gamma();
5+
| -- move occurs because `g1` has type `<&B as Beta>::Gamma`, which does not implement the `Copy` trait
6+
LL | a(g1) + a(g1)
7+
| -- ^^ value used here after move
8+
| |
9+
| value moved here
10+
|
11+
note: consider changing this parameter type in function `a` to borrow instead if owning the value isn't necessary
12+
--> $DIR/region-var-in-moved-ty-issue-133118.rs:12:24
13+
|
14+
LL | pub fn a<T: Alpha>(_x: T) -> usize {
15+
| - ^ this parameter takes ownership of the value
16+
| |
17+
| in this function
18+
19+
error: aborting due to 1 previous error
20+
21+
For more information about this error, try `rustc --explain E0382`.

0 commit comments

Comments
 (0)