diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2024-05-04 12:37:23 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-05-04 12:37:23 +0200 |
| commit | b0715b4e572d08e1d07963e6913d15a73b046c29 (patch) | |
| tree | e0289e6b01c3c886aecf3a14ba2b0f4f64de6205 | |
| parent | 81b43b759cd7089479aff743993d058e0f381149 (diff) | |
| parent | e404e7a8bdca1d517ffa1c5b56ad2513413db9c3 (diff) | |
| download | rust-b0715b4e572d08e1d07963e6913d15a73b046c29.tar.gz rust-b0715b4e572d08e1d07963e6913d15a73b046c29.zip | |
Rollup merge of #124692 - workingjubilee:document-no-double-pointer-coercion-happens, r=compiler-errors
We do not coerce `&mut &mut T -> *mut mut T` Resolves #34117 by declaring it to be "working as intended" until someone RFCs it or whatever other lang proposal would be required. It seems a bit of a footgun, but perhaps there are strong reasons to allow it anyways. Seeing as how I often have to be mindful to not allow a pointer to coerce the wrong way in my FFI work, I am inclined to think not, but perhaps it's fine in some use-case and that's actually more common?
| -rw-r--r-- | tests/ui/coercion/mut-mut-wont-coerce.rs | 43 | ||||
| -rw-r--r-- | tests/ui/coercion/mut-mut-wont-coerce.stderr | 19 |
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`. |
