Skip to content

Instantly share code, notes, and snippets.

@bgamari
Last active August 29, 2015 14:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save bgamari/d3e3a7a6b83c1bfaa00e to your computer and use it in GitHub Desktop.
Save bgamari/d3e3a7a6b83c1bfaa00e to your computer and use it in GitHub Desktop.
#![feature(unsafe_destructor)]
use std::ty::Unsafe;
use std::kinds::marker::InvariantType;
struct AReg1 {
value: Unsafe<u32>
}
struct AReg1Value {
value: u32,
}
impl AReg1Value {
pub fn new<'a>(reg: &'a AReg1) -> AReg1Value {
unsafe {
AReg1Value {value: *reg.value.get()}
}
}
pub fn get_field1(&self) -> bool {
(self.value >> 0) & 1 != 0
}
pub fn get_field2(&self) -> u32 {
(self.value >> 1) & 7
}
pub fn get_field3(&self) -> bool {
(self.value >> 5) & 1 != 0
}
}
/// This represents the value of a particular register named AReg1 and
/// can be used to manipulate the fields of this register atomically
struct AReg1Updater<'a> {
value: u32,
mask: u32,
// this may need to turn into a raw pointer due to unsafe destructors
reg: &'a AReg1,
}
impl<'a> AReg1Updater<'a> {
pub fn new(reg: &'a AReg1) -> AReg1Updater<'a> {
AReg1Updater {value: 0, mask: 0, reg: reg}
}
/// bit 0
pub fn set_field1<'b>(&'b mut self, value: bool) -> &'b mut AReg1Updater<'a> {
self.value = (!(1<<0) & self.value) | ((value as u32 & 1) << 0);
self.mask = self.mask | 1;
self
}
/// bits 1..4
pub fn set_field2<'b>(&'b mut self, value: u32) -> &'b mut AReg1Updater<'a> {
self.value = (!(7<<1) & self.value) | ((value as u32 & 0x7) << 1);
self.mask = self.mask | (7<<1);
self
}
/// bit 5: a write-to-clear flag
pub fn clear_field3<'b>(&'b mut self) -> &'b mut AReg1Updater<'a> {
self.value = self.value | (1<<5);
self.mask = self.mask | (1<<5);
self
}
}
#[unsafe_destructor]
impl<'a> Drop for AReg1Updater<'a> {
fn drop(&mut self) {
let clear_mask: u32 = 1 << 5;
if self.mask != 0 {
unsafe {
let old_value: u32 = *self.reg.value.get() & !clear_mask & !self.mask;
*self.reg.value.get() = self.value | old_value;
}
}
}
}
impl AReg1 {
fn get<'a>(&'a self) -> AReg1Value {
AReg1Value::new(self)
}
fn set_field1<'a>(&'a self, value: bool) -> AReg1Updater<'a> {
let mut a = AReg1Updater::new(self);
a.set_field1(value);
a
}
//fn get_field1<'a>(&'a self) -> u32 { ... }
//fn set_field2<'a>(&'a self, value: u32) -> AReg1Updater<'a> { ... }
//fn get_field2<'a>(&'a self) -> u32 { ... }
//fn set_field3<'a>(&'a self, value: bool) -> AReg1Updater<'a> { ... }
//fn get_field3<'a>(&'a self) -> bool { ... }
}
static mut areg1: AReg1 =
AReg1 { value: Unsafe {value: 0,
marker1: InvariantType }};
fn main() {
unsafe {
areg1
.set_field1(true)
.set_field2(5)
.clear_field3();
println!("field1 = {}", areg1.get().get_field1());
println!("field2 = {}", areg1.get().get_field2());
}
}
@bgamari
Copy link
Author

bgamari commented Jul 9, 2014

$ rustc register.rs
test.rs:41:53: 41:57 error: cannot infer an appropriate lifetime for automatic coercion due to conflicting requirements
test.rs:41     &AReg1 {value: *self.value.get(), mask: 0, reg: self}
                                                               ^~~~
test.rs:41:53: 41:57 note: first, the lifetime cannot outlive the expression at 41:52...
test.rs:41     &AReg1 {value: *self.value.get(), mask: 0, reg: self}
                                                               ^~~~
test.rs:41:53: 41:57 note: ...so that automatically reference is valid at the time of borrow
test.rs:41     &AReg1 {value: *self.value.get(), mask: 0, reg: self}
                                                               ^~~~
test.rs:40:43: 42:4 note: but, the lifetime must be valid for the lifetime 'a as defined on the block at 40:42...
test.rs:40   fn deref<'a>(&'a self) -> &'a AReg1<'a> {
test.rs:41     &AReg1 {value: *self.value.get(), mask: 0, reg: self}
test.rs:42   }
test.rs:41:5: 41:58 note: ...so that types are compatible (expected `&'a AReg1<'a>` but found `&AReg1<'_>`)
test.rs:41     &AReg1 {value: *self.value.get(), mask: 0, reg: self}
               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
test.rs:40:3: 42:4 error: method `deref` has an incompatible type for trait: expected concrete lifetime, but found bound lifetime parameter 'a
test.rs:40   fn deref<'a>(&'a self) -> &'a AReg1<'a> {
test.rs:41     &AReg1 {value: *self.value.get(), mask: 0, reg: self}
test.rs:42   }
test.rs:40:43: 42:4 note: expected concrete lifetime is the lifetime 'b as defined on the block at 40:42
test.rs:40   fn deref<'a>(&'a self) -> &'a AReg1<'a> {
test.rs:41     &AReg1 {value: *self.value.get(), mask: 0, reg: self}
test.rs:42   }
error: aborting due to 2 previous errors

@bgamari
Copy link
Author

bgamari commented Jul 9, 2014

$ rustc test.rs
error: internal compiler error: unexpected failure
note: the compiler hit an unexpected failure path. this is a bug.
note: we would appreciate a bug report: http://doc.rust-lang.org/complement-bugreport.html
note: run with `RUST_BACKTRACE=1` for a backtrace
task 'rustc' failed at 'index out of bounds: the len is 0 but the index is 0', /opt/exp/rust/src/librustc/middle/subst.rs:405

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment