| //@ check-pass | |
| use std::sync::Mutex; | |
| struct Foo { | |
| x: usize | |
| } | |
| const fn foo() -> Foo { | |
| Foo { x: 0 } | |
| } | |
| impl Foo { | |
| const fn bar(&mut self) -> usize { | |
| self.x = 1; | |
| self.x | |
| } | |
| } | |
| const fn baz(foo: &mut Foo) -> usize { | |
| let x = &mut foo.x; | |
| *x = 2; | |
| *x | |
| } | |
| const fn bazz(foo: &mut Foo) -> usize { | |
| foo.x = 3; | |
| foo.x | |
| } | |
| // Empty slices get promoted so this passes the static checks. | |
| // Make sure it also passes the dynamic checks. | |
| static MUTABLE_REFERENCE_HOLDER: Mutex<&mut [u8]> = Mutex::new(&mut []); | |
| // This variant with a non-empty slice also seems entirely reasonable. | |
| static MUTABLE_REFERENCE_HOLDER2: Mutex<&mut [u8]> = unsafe { | |
| static mut FOO: [u8; 1] = [42]; // a private static that we are sure nobody else will reference | |
| Mutex::new(&mut *std::ptr::addr_of_mut!(FOO)) | |
| }; | |
| fn main() { | |
| let _: [(); foo().bar()] = [(); 1]; | |
| let _: [(); baz(&mut foo())] = [(); 2]; | |
| let _: [(); bazz(&mut foo())] = [(); 3]; | |
| } |