From e404e7a8bdca1d517ffa1c5b56ad2513413db9c3 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Fri, 3 May 2024 19:55:07 -0700 Subject: [PATCH] We do not coerce &mut &mut T -> *mut mut T --- tests/ui/coercion/mut-mut-wont-coerce.rs | 43 ++++++++++++++++++++ tests/ui/coercion/mut-mut-wont-coerce.stderr | 19 +++++++++ 2 files changed, 62 insertions(+) create mode 100644 tests/ui/coercion/mut-mut-wont-coerce.rs create mode 100644 tests/ui/coercion/mut-mut-wont-coerce.stderr 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(*mut T); + +impl SmartPtr { + fn get_addr(&mut self) -> &mut *mut T { + &mut self.0 + } +} + +impl Deref for SmartPtr { + type Target = T; + fn deref(&self) -> &T { + unsafe { &*self.0 } + } +} +impl DerefMut for SmartPtr { + 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 = 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(ptr: &mut SmartPtr) -> &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`.