about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs26
-rw-r--r--tests/ui/moves/moved-value-on-as-ref-arg.fixed4
-rw-r--r--tests/ui/moves/moved-value-on-as-ref-arg.rs4
-rw-r--r--tests/ui/moves/region-var-in-moved-ty-issue-133118.rs25
-rw-r--r--tests/ui/moves/region-var-in-moved-ty-issue-133118.stderr21
5 files changed, 60 insertions, 20 deletions
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 454fd14ea74..51c2282422e 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -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,
                 ))
             })
         }) {
diff --git a/tests/ui/moves/moved-value-on-as-ref-arg.fixed b/tests/ui/moves/moved-value-on-as-ref-arg.fixed
index 292fa98a3f7..97bfe094ce5 100644
--- a/tests/ui/moves/moved-value-on-as-ref-arg.fixed
+++ b/tests/ui/moves/moved-value-on-as-ref-arg.fixed
@@ -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;
diff --git a/tests/ui/moves/moved-value-on-as-ref-arg.rs b/tests/ui/moves/moved-value-on-as-ref-arg.rs
index 632af9efcda..fed41cf710d 100644
--- a/tests/ui/moves/moved-value-on-as-ref-arg.rs
+++ b/tests/ui/moves/moved-value-on-as-ref-arg.rs
@@ -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;
diff --git a/tests/ui/moves/region-var-in-moved-ty-issue-133118.rs b/tests/ui/moves/region-var-in-moved-ty-issue-133118.rs
new file mode 100644
index 00000000000..a49370e315d
--- /dev/null
+++ b/tests/ui/moves/region-var-in-moved-ty-issue-133118.rs
@@ -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() {}
diff --git a/tests/ui/moves/region-var-in-moved-ty-issue-133118.stderr b/tests/ui/moves/region-var-in-moved-ty-issue-133118.stderr
new file mode 100644
index 00000000000..691625d042d
--- /dev/null
+++ b/tests/ui/moves/region-var-in-moved-ty-issue-133118.stderr
@@ -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`.