-
Notifications
You must be signed in to change notification settings - Fork 32
/
mut-mut-wont-coerce.rs
43 lines (36 loc) · 1.18 KB
/
mut-mut-wont-coerce.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
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()
}