Skip to content

Commit

Permalink
Rollup merge of #124692 - workingjubilee:document-no-double-pointer-c…
Browse files Browse the repository at this point in the history
…oercion-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?
  • Loading branch information
matthiaskrgr authored May 4, 2024
2 parents 31099d5 + e404e7a commit e82ed82
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 0 deletions.
43 changes: 43 additions & 0 deletions tests/ui/coercion/mut-mut-wont-coerce.rs
Original file line number Diff line number Diff line change
@@ -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()
}
19 changes: 19 additions & 0 deletions tests/ui/coercion/mut-mut-wont-coerce.stderr
Original file line number Diff line number Diff line change
@@ -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`.

0 comments on commit e82ed82

Please sign in to comment.