about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2025-01-31 02:04:10 +0000
committerMichael Goulet <michael@errs.io>2025-01-31 17:40:28 +0000
commitb63341e892447f73888f858052bca57495ee8d67 (patch)
tree33f254d4c70018d8fd6d232f904c2c682e10a78a
parentfc1a9186dcdad111fd99ddd38bd961a8a205c380 (diff)
downloadrust-b63341e892447f73888f858052bca57495ee8d67.tar.gz
rust-b63341e892447f73888f858052bca57495ee8d67.zip
Enforce unsafe binders must be Copy (for now)
-rw-r--r--compiler/rustc_codegen_cranelift/src/base.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs21
-rw-r--r--src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs1
-rw-r--r--tests/ui/unsafe-binders/moves.rs15
-rw-r--r--tests/ui/unsafe-binders/moves.stderr98
5 files changed, 98 insertions, 41 deletions
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index ea37e19099a..97d8baa6157 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -915,6 +915,10 @@ fn codegen_stmt<'tcx>(
                     }
                     crate::discriminant::codegen_set_discriminant(fx, lval, variant_index);
                 }
+                Rvalue::WrapUnsafeBinder(ref operand, _to_ty) => {
+                    let operand = codegen_operand(fx, operand);
+                    lval.write_cvalue_transmute(fx, operand);
+                }
             }
         }
         StatementKind::StorageLive(_)
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index 20b675bcb76..0afe483f721 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -828,8 +828,25 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
                 // Let the visitor iterate into the argument/return
                 // types appearing in the fn signature.
             }
-            ty::UnsafeBinder(_) => {
-                // FIXME(unsafe_binders): We should also recurse into the binder here.
+            ty::UnsafeBinder(ty) => {
+                // FIXME(unsafe_binders): For now, we have no way to express
+                // that a type must be `ManuallyDrop` OR `Copy` (or a pointer).
+                if !ty.has_escaping_bound_vars() {
+                    self.out.push(traits::Obligation::new(
+                        self.tcx(),
+                        self.cause(ObligationCauseCode::Misc),
+                        self.param_env,
+                        ty.map_bound(|ty| {
+                            ty::TraitRef::new(
+                                self.tcx(),
+                                self.tcx().require_lang_item(LangItem::Copy, Some(self.span)),
+                                [ty],
+                            )
+                        }),
+                    ));
+                }
+
+                // We recurse into the binder below.
             }
 
             ty::Dynamic(data, r, _) => {
diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
index 916017b09dd..0aaef91e48a 100644
--- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
+++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
@@ -116,6 +116,7 @@ fn check_rvalue<'tcx>(
         Rvalue::CopyForDeref(place) => check_place(tcx, *place, span, body, msrv),
         Rvalue::Repeat(operand, _)
         | Rvalue::Use(operand)
+        | Rvalue::WrapUnsafeBinder(operand, _)
         | Rvalue::Cast(
             CastKind::PointerWithExposedProvenance
             | CastKind::IntToInt
diff --git a/tests/ui/unsafe-binders/moves.rs b/tests/ui/unsafe-binders/moves.rs
index 1f61d2bf144..5bfcee62402 100644
--- a/tests/ui/unsafe-binders/moves.rs
+++ b/tests/ui/unsafe-binders/moves.rs
@@ -1,17 +1,20 @@
+//@ known-bug: unknown
+
 #![feature(unsafe_binders)]
-//~^ WARN the feature `unsafe_binders` is incomplete
+// FIXME(unsafe_binders) ~^ WARN the feature `unsafe_binders` is incomplete
 
 use std::unsafe_binder::{wrap_binder, unwrap_binder};
-use std::mem::drop;
+use std::mem::{drop, ManuallyDrop};
 
-struct NotCopy;
+struct NotCopyInner;
+type NotCopy = ManuallyDrop<NotCopyInner>;
 
 fn use_after_wrap() {
     unsafe {
         let base = NotCopy;
         let binder: unsafe<> NotCopy = wrap_binder!(base);
         drop(base);
-        //~^ ERROR use of moved value: `base`
+        // FIXME(unsafe_binders) ~^ ERROR use of moved value: `base`
     }
 }
 
@@ -20,7 +23,7 @@ fn move_out_of_wrap() {
         let binder: unsafe<> NotCopy = wrap_binder!(NotCopy);
         drop(unwrap_binder!(binder));
         drop(unwrap_binder!(binder));
-        //~^ ERROR use of moved value: `binder`
+        // FIXME(unsafe_binders) ~^ ERROR use of moved value: `binder`
     }
 }
 
@@ -31,7 +34,7 @@ fn not_conflicting() {
         drop(unwrap_binder!(binder).1);
         // ^ NOT a problem.
         drop(unwrap_binder!(binder).0);
-        //~^ ERROR use of moved value: `binder.0`
+        // FIXME(unsafe_binders) ~^ ERROR use of moved value: `binder.0`
     }
 }
 
diff --git a/tests/ui/unsafe-binders/moves.stderr b/tests/ui/unsafe-binders/moves.stderr
index d90823bf7e2..ca507964008 100644
--- a/tests/ui/unsafe-binders/moves.stderr
+++ b/tests/ui/unsafe-binders/moves.stderr
@@ -1,5 +1,37 @@
+error[E0423]: expected value, found type alias `NotCopy`
+  --> $DIR/moves.rs:14:20
+   |
+LL |         let base = NotCopy;
+   |                    ^^^^^^^
+   |
+   = note: can't use a type alias as a constructor
+
+error[E0423]: expected value, found type alias `NotCopy`
+  --> $DIR/moves.rs:23:53
+   |
+LL |         let binder: unsafe<> NotCopy = wrap_binder!(NotCopy);
+   |                                                     ^^^^^^^
+   |
+   = note: can't use a type alias as a constructor
+
+error[E0423]: expected value, found type alias `NotCopy`
+  --> $DIR/moves.rs:32:65
+   |
+LL |         let binder: unsafe<> (NotCopy, NotCopy) = wrap_binder!((NotCopy, NotCopy));
+   |                                                                 ^^^^^^^
+   |
+   = note: can't use a type alias as a constructor
+
+error[E0423]: expected value, found type alias `NotCopy`
+  --> $DIR/moves.rs:32:74
+   |
+LL |         let binder: unsafe<> (NotCopy, NotCopy) = wrap_binder!((NotCopy, NotCopy));
+   |                                                                          ^^^^^^^
+   |
+   = note: can't use a type alias as a constructor
+
 warning: the feature `unsafe_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/moves.rs:1:12
+  --> $DIR/moves.rs:3:12
    |
 LL | #![feature(unsafe_binders)]
    |            ^^^^^^^^^^^^^^
@@ -7,47 +39,47 @@ LL | #![feature(unsafe_binders)]
    = note: see issue #130516 <https://github.com/rust-lang/rust/issues/130516> for more information
    = note: `#[warn(incomplete_features)]` on by default
 
-error[E0382]: use of moved value: `base`
-  --> $DIR/moves.rs:13:14
+error[E0277]: the trait bound `NotCopyInner: Copy` is not satisfied
+  --> $DIR/moves.rs:15:21
    |
-LL |         let base = NotCopy;
-   |             ---- move occurs because `base` has type `NotCopy`, which does not implement the `Copy` trait
 LL |         let binder: unsafe<> NotCopy = wrap_binder!(base);
-   |                                                     ---- value moved here
-LL |         drop(base);
-   |              ^^^^ value used here after move
+   |                     ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `NotCopyInner`
    |
-note: if `NotCopy` implemented `Clone`, you could clone the value
-  --> $DIR/moves.rs:7:1
+   = note: required for `ManuallyDrop<NotCopyInner>` to implement `Copy`
+help: consider annotating `NotCopyInner` with `#[derive(Copy)]`
+   |
+LL + #[derive(Copy)]
+LL | struct NotCopyInner;
    |
-LL | struct NotCopy;
-   | ^^^^^^^^^^^^^^ consider implementing `Clone` for this type
-...
-LL |         let binder: unsafe<> NotCopy = wrap_binder!(base);
-   |                                                     ---- you could clone this value
 
-error[E0382]: use of moved value: `binder`
-  --> $DIR/moves.rs:22:14
+error[E0277]: the trait bound `NotCopyInner: Copy` is not satisfied
+  --> $DIR/moves.rs:23:21
+   |
+LL |         let binder: unsafe<> NotCopy = wrap_binder!(NotCopy);
+   |                     ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `NotCopyInner`
+   |
+   = note: required for `ManuallyDrop<NotCopyInner>` to implement `Copy`
+help: consider annotating `NotCopyInner` with `#[derive(Copy)]`
    |
-LL |         drop(unwrap_binder!(binder));
-   |              ---------------------- value moved here
-LL |         drop(unwrap_binder!(binder));
-   |              ^^^^^^^^^^^^^^^^^^^^^^ value used here after move
+LL + #[derive(Copy)]
+LL | struct NotCopyInner;
    |
-   = note: move occurs because `binder` has type `NotCopy`, which does not implement the `Copy` trait
-   = note: this error originates in the macro `unwrap_binder` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0382]: use of moved value: `binder.0`
-  --> $DIR/moves.rs:33:14
+error[E0277]: the trait bound `NotCopyInner: Copy` is not satisfied
+  --> $DIR/moves.rs:32:21
+   |
+LL |         let binder: unsafe<> (NotCopy, NotCopy) = wrap_binder!((NotCopy, NotCopy));
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `NotCopyInner`
+   |
+   = note: required for `ManuallyDrop<NotCopyInner>` to implement `Copy`
+   = note: required because it appears within the type `(ManuallyDrop<NotCopyInner>, ManuallyDrop<NotCopyInner>)`
+help: consider annotating `NotCopyInner` with `#[derive(Copy)]`
    |
-LL |         drop(unwrap_binder!(binder).0);
-   |              ------------------------ value moved here
-...
-LL |         drop(unwrap_binder!(binder).0);
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^ value used here after move
+LL + #[derive(Copy)]
+LL | struct NotCopyInner;
    |
-   = note: move occurs because `binder.0` has type `NotCopy`, which does not implement the `Copy` trait
 
-error: aborting due to 3 previous errors; 1 warning emitted
+error: aborting due to 7 previous errors; 1 warning emitted
 
-For more information about this error, try `rustc --explain E0382`.
+Some errors have detailed explanations: E0277, E0423.
+For more information about an error, try `rustc --explain E0277`.