Skip to content

Commit e7618ca

Browse files
committed
Auto merge of #81 - japaric:singleton, r=japaric
[RFC] initialize singletons at runtime This PR changes how the singletons are initialized. The advantage of initializing a singleton at runtime is that the initial value is not constrained to only what works in const context. The disadvantage is that this approach will use up more Flash. With the new approach, `singleton!(_: [u8; 1024] = [0; 1024])` will invoke a memcpy at the caller site; with the old approach, the array would have been initialized (zeroed) during startup. The following code works with the new approach, but doesn't with the old one. ``` rust let x = 0; let y = singleton!(_: u32 = x); ``` cc @therealprof @hannobraun
2 parents c921d43 + 032af4b commit e7618ca

File tree

3 files changed

+51
-6
lines changed

3 files changed

+51
-6
lines changed

Cargo.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ version = "0.4.2"
1313
aligned = "0.1.1"
1414
bare-metal = "0.1.0"
1515
volatile-register = "0.2.0"
16+
untagged-option = "0.1.1"
1617

1718
[features]
18-
cm7-r0p1 = []
19+
cm7-r0p1 = []

src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
extern crate aligned;
1717
extern crate bare_metal;
18+
extern crate untagged_option;
1819
extern crate volatile_register;
1920

2021
#[macro_use]
@@ -31,3 +32,4 @@ pub mod peripheral;
3132
pub mod register;
3233

3334
pub use peripheral::Peripherals;
35+
pub use untagged_option::UntaggedOption;

src/macros.rs

+47-5
Original file line numberDiff line numberDiff line change
@@ -52,17 +52,59 @@ macro_rules! iprintln {
5252
#[macro_export]
5353
macro_rules! singleton {
5454
(: $ty:ty = $expr:expr) => {
55-
$crate::interrupt::free(|_| unsafe {
55+
$crate::interrupt::free(|_| {
5656
static mut USED: bool = false;
57-
static mut VAR: $ty = $expr;
57+
static mut VAR: $crate::UntaggedOption<$ty> = $crate::UntaggedOption { none: () };
5858

59-
if USED {
59+
60+
#[allow(unsafe_code)]
61+
let used = unsafe { USED };
62+
if used {
6063
None
6164
} else {
62-
USED = true;
63-
let var: &'static mut _ = &mut VAR;
65+
#[allow(unsafe_code)]
66+
unsafe { USED = true }
67+
68+
let expr = $expr;
69+
70+
#[allow(unsafe_code)]
71+
unsafe { VAR.some = expr }
72+
73+
#[allow(unsafe_code)]
74+
let var: &'static mut _ = unsafe { &mut VAR.some };
75+
6476
Some(var)
6577
}
6678
})
6779
}
6880
}
81+
82+
83+
/// ``` compile_fail
84+
/// #[macro_use(singleton)]
85+
/// extern crate cortex_m;
86+
///
87+
/// fn main() {}
88+
///
89+
/// fn foo() {
90+
/// // check that the call to `uninitialized` requires unsafe
91+
/// singleton!(: u8 = std::mem::uninitialized());
92+
/// }
93+
/// ```
94+
#[allow(dead_code)]
95+
const CFAIL: () = ();
96+
97+
/// ```
98+
/// #![deny(unsafe_code)]
99+
/// #[macro_use(singleton)]
100+
/// extern crate cortex_m;
101+
///
102+
/// fn main() {}
103+
///
104+
/// fn foo() {
105+
/// // check that calls to `singleton!` don't trip the `unsafe_code` lint
106+
/// singleton!(: u8 = 0);
107+
/// }
108+
/// ```
109+
#[allow(dead_code)]
110+
const CPASS: () = ();

0 commit comments

Comments
 (0)