-
Notifications
You must be signed in to change notification settings - Fork 126
Automatically use the allocation-free API for Rust 1.27.0+. #103
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
28cc070
1a18c65
cdf6323
f85db0b
0463a90
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
extern crate rustc_version; | ||
|
||
use rustc_version::{version, Version}; | ||
|
||
fn main() { | ||
let is_var_set = |s| std::env::var_os(s).is_some(); | ||
|
||
// one can manually set a cfg to force an impl -- mostly useful for our own testing | ||
let force_heap_cfg = is_var_set("CARGO_CFG_LAZY_STATIC_HEAP_IMPL"); | ||
let force_inline_cfg = is_var_set("CARGO_CFG_LAZY_STATIC_INLINE_IMPL"); | ||
let force_spin_cfg = is_var_set("CARGO_CFG_LAZY_STATIC_SPIN_IMPL"); | ||
|
||
let impls_forced = [force_heap_cfg, force_inline_cfg, force_spin_cfg] | ||
.into_iter() | ||
.filter(|&&f| f) | ||
.count(); | ||
|
||
assert!( | ||
impls_forced <= 1, | ||
"lazy_static can only be built with one configuration at a time." | ||
); | ||
|
||
let nightly_feature_enabled = is_var_set("CARGO_FEATURE_NIGHTLY"); | ||
let spin_feature_enabled = is_var_set("CARGO_FEATURE_SPIN_NO_STD"); | ||
|
||
let version_geq_122 = version().unwrap() >= Version::new(1, 22, 0); | ||
let drop_in_static_supported = version_geq_122 || nightly_feature_enabled; | ||
|
||
// precedence: | ||
// 1. explicit requests via cfg or spin_no_std feature | ||
// 2. inline impl with newer rustc version or nightly feature (latter for backcompat) | ||
// 3. fallback to allocating implementation | ||
let impl_name = if force_heap_cfg { | ||
"heap" | ||
} else if force_inline_cfg { | ||
"inline" | ||
} else if force_spin_cfg || spin_feature_enabled { | ||
"spin" | ||
} else if drop_in_static_supported { | ||
"inline" | ||
} else { | ||
"heap" | ||
}; | ||
|
||
println!("cargo:rustc-cfg=lazy_static_{}_impl", impl_name); | ||
|
||
let version_geq_127 = version().unwrap() >= Version::new(1, 27, 0); | ||
let core_unreachable_unchecked_supported = version_geq_127 || nightly_feature_enabled; | ||
if core_unreachable_unchecked_supported { | ||
println!("cargo:rustc-cfg=lazy_static_core_unreachable_unchecked"); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,19 +5,22 @@ | |
// http://opensource.org/licenses/MIT>, at your option. This file may not be | ||
// copied, modified, or distributed except according to those terms. | ||
|
||
extern crate std; | ||
extern crate core; | ||
extern crate std; | ||
|
||
use self::std::prelude::v1::*; | ||
use self::std::sync::Once; | ||
pub use self::std::sync::ONCE_INIT; | ||
|
||
pub struct Lazy<T: Sync>(pub Option<T>, pub Once); | ||
pub struct Lazy<T: Sync>(Option<T>, Once); | ||
|
||
impl<T: Sync> Lazy<T> { | ||
pub const INIT: Self = Lazy(None, ONCE_INIT); | ||
|
||
#[inline(always)] | ||
pub fn get<F>(&'static mut self, f: F) -> &T | ||
where F: FnOnce() -> T | ||
where | ||
F: FnOnce() -> T, | ||
{ | ||
{ | ||
let r = &mut self.0; | ||
|
@@ -28,7 +31,7 @@ impl<T: Sync> Lazy<T> { | |
unsafe { | ||
match self.0 { | ||
Some(ref x) => x, | ||
None => core::hint::unreachable_unchecked(), | ||
None => unreachable_unchecked(), | ||
} | ||
} | ||
} | ||
|
@@ -40,6 +43,18 @@ unsafe impl<T: Sync> Sync for Lazy<T> {} | |
#[doc(hidden)] | ||
macro_rules! __lazy_static_create { | ||
($NAME:ident, $T:ty) => { | ||
static mut $NAME: $crate::lazy::Lazy<$T> = $crate::lazy::Lazy(None, $crate::lazy::ONCE_INIT); | ||
} | ||
static mut $NAME: $crate::lazy::Lazy<$T> = $crate::lazy::Lazy::INIT; | ||
}; | ||
} | ||
|
||
#[cfg(lazy_static_core_unreachable_unchecked)] | ||
use core::hint::unreachable_unchecked; | ||
|
||
#[cfg(not(lazy_static_core_unreachable_unchecked))] | ||
/// Polyfill for core::hint::unreachable_unchecked. Included to support Rust prior to 1.27. See | ||
/// [issue #102](https://github.com/rust-lang-nursery/lazy-static.rs/issues/102#issuecomment-400959779) | ||
/// for details. | ||
unsafe fn unreachable_unchecked() -> ! { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You don't need to do this yourself, turns out, https://docs.rs/unreachable exists. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hm, I think it's reasonable in this case for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah that's fine, if the rationalization is added to the comment. |
||
enum Void {} | ||
match std::mem::uninitialized::<Void>() {} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to bother with
core::hint::unreachable_unchecked
at all with our polyfill?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope, we can wait until the minimum version is raised for some other reason, to switch to the
std
version.