mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-21 22:34:05 +00:00
suggest_borrow_generic_arg
: instantiate clauses properly
Fixes issue 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.
This commit is contained in:
parent
5afd5ad29c
commit
546ba3d310
@ -27,7 +27,7 @@ use rustc_middle::mir::{
|
||||
};
|
||||
use rustc_middle::ty::print::PrintTraitRefExt as _;
|
||||
use rustc_middle::ty::{
|
||||
self, ClauseKind, PredicateKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor, Upcast,
|
||||
self, PredicateKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor, Upcast,
|
||||
suggest_constraining_type_params,
|
||||
};
|
||||
use rustc_middle::util::CallKind;
|
||||
@ -649,11 +649,11 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||
) -> Option<ty::Mutability> {
|
||||
let tcx = self.infcx.tcx;
|
||||
let sig = tcx.fn_sig(callee_did).instantiate_identity().skip_binder();
|
||||
let clauses = tcx.predicates_of(callee_did).instantiate_identity(self.infcx.tcx).predicates;
|
||||
let clauses = tcx.predicates_of(callee_did);
|
||||
|
||||
// First, is there at least one method on one of `param`'s trait bounds?
|
||||
// This keeps us from suggesting borrowing the argument to `mem::drop`, e.g.
|
||||
if !clauses.iter().any(|clause| {
|
||||
if !clauses.instantiate_identity(tcx).predicates.iter().any(|clause| {
|
||||
clause.as_trait_clause().is_some_and(|tc| {
|
||||
tc.self_ty().skip_binder().is_param(param.index)
|
||||
&& tc.polarity() == ty::PredicatePolarity::Positive
|
||||
@ -700,23 +700,17 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test the callee's predicates, substituting a reference in for the self ty
|
||||
// in bounds on `param`.
|
||||
clauses.iter().all(|&clause| {
|
||||
let clause_for_ref = clause.kind().map_bound(|kind| match kind {
|
||||
ClauseKind::Trait(c) if c.self_ty().is_param(param.index) => {
|
||||
ClauseKind::Trait(c.with_self_ty(tcx, ref_ty))
|
||||
}
|
||||
ClauseKind::Projection(c) if c.self_ty().is_param(param.index) => {
|
||||
ClauseKind::Projection(c.with_self_ty(tcx, ref_ty))
|
||||
}
|
||||
_ => kind,
|
||||
});
|
||||
// Test the callee's predicates, substituting in `ref_ty` for the moved argument type.
|
||||
clauses.instantiate(tcx, new_args).predicates.iter().all(|&(mut clause)| {
|
||||
// Normalize before testing to see through type aliases and projections.
|
||||
if let Ok(normalized) = tcx.try_normalize_erasing_regions(self.param_env, clause) {
|
||||
clause = normalized;
|
||||
}
|
||||
self.infcx.predicate_must_hold_modulo_regions(&Obligation::new(
|
||||
tcx,
|
||||
ObligationCause::dummy(),
|
||||
self.param_env,
|
||||
ty::EarlyBinder::bind(clause_for_ref).instantiate(tcx, generic_args),
|
||||
clause,
|
||||
))
|
||||
})
|
||||
}) {
|
||||
|
@ -18,8 +18,8 @@ impl AsMut<Bar> for Bar {
|
||||
|
||||
fn foo<T: AsRef<Bar>>(_: T) {}
|
||||
fn qux<T: AsMut<Bar>>(_: T) {}
|
||||
fn bat<T: Borrow<T>>(_: T) {}
|
||||
fn baz<T: BorrowMut<T>>(_: T) {}
|
||||
fn bat<T: Borrow<Bar>>(_: T) {}
|
||||
fn baz<T: BorrowMut<Bar>>(_: T) {}
|
||||
|
||||
pub fn main() {
|
||||
let bar = Bar;
|
||||
|
@ -18,8 +18,8 @@ impl AsMut<Bar> for Bar {
|
||||
|
||||
fn foo<T: AsRef<Bar>>(_: T) {}
|
||||
fn qux<T: AsMut<Bar>>(_: T) {}
|
||||
fn bat<T: Borrow<T>>(_: T) {}
|
||||
fn baz<T: BorrowMut<T>>(_: T) {}
|
||||
fn bat<T: Borrow<Bar>>(_: T) {}
|
||||
fn baz<T: BorrowMut<Bar>>(_: T) {}
|
||||
|
||||
pub fn main() {
|
||||
let bar = Bar;
|
||||
|
25
tests/ui/moves/region-var-in-moved-ty-issue-133118.rs
Normal file
25
tests/ui/moves/region-var-in-moved-ty-issue-133118.rs
Normal file
@ -0,0 +1,25 @@
|
||||
//! regression test for #133118
|
||||
|
||||
pub trait Alpha {
|
||||
fn y(self) -> usize;
|
||||
}
|
||||
|
||||
pub trait Beta {
|
||||
type Gamma;
|
||||
fn gamma(&self) -> Self::Gamma;
|
||||
}
|
||||
|
||||
pub fn a<T: Alpha>(_x: T) -> usize {
|
||||
todo!();
|
||||
}
|
||||
|
||||
pub fn x<B>(beta: &B) -> usize
|
||||
where
|
||||
for<'a> &'a B: Beta,
|
||||
for<'a> <&'a B as Beta>::Gamma: Alpha,
|
||||
{
|
||||
let g1 = beta.gamma();
|
||||
a(g1) + a(g1) //~ ERROR use of moved value: `g1` [E0382]
|
||||
}
|
||||
|
||||
pub fn main() {}
|
21
tests/ui/moves/region-var-in-moved-ty-issue-133118.stderr
Normal file
21
tests/ui/moves/region-var-in-moved-ty-issue-133118.stderr
Normal file
@ -0,0 +1,21 @@
|
||||
error[E0382]: use of moved value: `g1`
|
||||
--> $DIR/region-var-in-moved-ty-issue-133118.rs:22:15
|
||||
|
|
||||
LL | let g1 = beta.gamma();
|
||||
| -- move occurs because `g1` has type `<&B as Beta>::Gamma`, which does not implement the `Copy` trait
|
||||
LL | a(g1) + a(g1)
|
||||
| -- ^^ value used here after move
|
||||
| |
|
||||
| value moved here
|
||||
|
|
||||
note: consider changing this parameter type in function `a` to borrow instead if owning the value isn't necessary
|
||||
--> $DIR/region-var-in-moved-ty-issue-133118.rs:12:24
|
||||
|
|
||||
LL | pub fn a<T: Alpha>(_x: T) -> usize {
|
||||
| - ^ this parameter takes ownership of the value
|
||||
| |
|
||||
| in this function
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0382`.
|
Loading…
Reference in New Issue
Block a user