about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--tests/ui/coercion/mut-mut-wont-coerce.rs43
-rw-r--r--tests/ui/coercion/mut-mut-wont-coerce.stderr19
2 files changed, 62 insertions, 0 deletions
diff --git a/tests/ui/coercion/mut-mut-wont-coerce.rs b/tests/ui/coercion/mut-mut-wont-coerce.rs
new file mode 100644
index 00000000000..e99566461a2
--- /dev/null
+++ b/tests/ui/coercion/mut-mut-wont-coerce.rs
@@ -0,0 +1,43 @@
+// Documents that Rust currently does not permit the coercion &mut &mut T -> *mut *mut T
+// Making this compile was a feature request in rust-lang/rust#34117 but this is currently
+// "working as intended". Allowing "deep pointer coercion" seems footgun-prone, and would
+// require proceeding carefully.
+use std::ops::{Deref, DerefMut};
+
+struct Foo(i32);
+
+struct SmartPtr<T>(*mut T);
+
+impl<T> SmartPtr<T> {
+    fn get_addr(&mut self) -> &mut *mut T {
+        &mut self.0
+    }
+}
+
+impl<T> Deref for SmartPtr<T> {
+    type Target = T;
+    fn deref(&self) -> &T {
+        unsafe { &*self.0 }
+    }
+}
+impl<T> DerefMut for SmartPtr<T> {
+    fn deref_mut(&mut self) -> &mut T {
+        unsafe { &mut *self.0 }
+    }
+}
+
+/// Puts a Foo into the pointer provided by the caller
+fn make_foo(_: *mut *mut Foo) {
+    unimplemented!()
+}
+
+fn main() {
+    let mut result: SmartPtr<Foo> = SmartPtr(std::ptr::null_mut());
+    make_foo(&mut &mut *result); //~ mismatched types
+                                 //~^ expected `*mut *mut Foo`, found `&mut &mut Foo`
+    make_foo(out(&mut result)); // works, but makes one wonder why above coercion cannot happen
+}
+
+fn out<T>(ptr: &mut SmartPtr<T>) -> &mut *mut T {
+    ptr.get_addr()
+}
diff --git a/tests/ui/coercion/mut-mut-wont-coerce.stderr b/tests/ui/coercion/mut-mut-wont-coerce.stderr
new file mode 100644
index 00000000000..5daf9cbd3d3
--- /dev/null
+++ b/tests/ui/coercion/mut-mut-wont-coerce.stderr
@@ -0,0 +1,19 @@
+error[E0308]: mismatched types
+  --> $DIR/mut-mut-wont-coerce.rs:36:14
+   |
+LL |     make_foo(&mut &mut *result);
+   |     -------- ^^^^^^^^^^^^^^^^^ expected `*mut *mut Foo`, found `&mut &mut Foo`
+   |     |
+   |     arguments to this function are incorrect
+   |
+   = note:    expected raw pointer `*mut *mut Foo`
+           found mutable reference `&mut &mut Foo`
+note: function defined here
+  --> $DIR/mut-mut-wont-coerce.rs:30:4
+   |
+LL | fn make_foo(_: *mut *mut Foo) {
+   |    ^^^^^^^^ ----------------
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.