From 472ca7159812f8c360697f63454ee7bda1e02570 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 22 Aug 2018 15:56:37 +0200 Subject: Implement the `min_const_fn` feature gate --- src/libstd/io/lazy.rs | 38 ++++++++++++++++++-------------------- src/libstd/io/stdio.rs | 20 ++++++++++++-------- 2 files changed, 30 insertions(+), 28 deletions(-) (limited to 'src/libstd/io') diff --git a/src/libstd/io/lazy.rs b/src/libstd/io/lazy.rs index 4fb367fb6ba..24965ff6931 100644 --- a/src/libstd/io/lazy.rs +++ b/src/libstd/io/lazy.rs @@ -18,7 +18,6 @@ pub struct Lazy { // We never call `lock.init()`, so it is UB to attempt to acquire this mutex reentrantly! lock: Mutex, ptr: Cell<*mut Arc>, - init: fn() -> Arc, } #[inline] @@ -26,33 +25,32 @@ const fn done() -> *mut Arc { 1_usize as *mut _ } unsafe impl Sync for Lazy {} -impl Lazy { - /// Safety: `init` must not call `get` on the variable that is being - /// initialized. - pub const unsafe fn new(init: fn() -> Arc) -> Lazy { +impl Lazy { + pub const fn new() -> Lazy { Lazy { lock: Mutex::new(), ptr: Cell::new(ptr::null_mut()), - init, } } +} - pub fn get(&'static self) -> Option> { - unsafe { - let _guard = self.lock.lock(); - let ptr = self.ptr.get(); - if ptr.is_null() { - Some(self.init()) - } else if ptr == done() { - None - } else { - Some((*ptr).clone()) - } +impl Lazy { + /// Safety: `init` must not call `get` on the variable that is being + /// initialized. + pub unsafe fn get(&'static self, init: fn() -> Arc) -> Option> { + let _guard = self.lock.lock(); + let ptr = self.ptr.get(); + if ptr.is_null() { + Some(self.init(init)) + } else if ptr == done() { + None + } else { + Some((*ptr).clone()) } } // Must only be called with `lock` held - unsafe fn init(&'static self) -> Arc { + unsafe fn init(&'static self, init: fn() -> Arc) -> Arc { // If we successfully register an at exit handler, then we cache the // `Arc` allocation in our own internal box (it will get deallocated by // the at exit handler). Otherwise we just return the freshly allocated @@ -66,8 +64,8 @@ impl Lazy { }); // This could reentrantly call `init` again, which is a problem // because our `lock` allows reentrancy! - // That's why `new` is unsafe and requires the caller to ensure no reentrancy happens. - let ret = (self.init)(); + // That's why `get` is unsafe and requires the caller to ensure no reentrancy happens. + let ret = init(); if registered.is_ok() { self.ptr.set(Box::into_raw(Box::new(ret.clone()))); } diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index 1f256f518c7..a413432cdaa 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -197,9 +197,11 @@ pub struct StdinLock<'a> { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn stdin() -> Stdin { - static INSTANCE: Lazy>>> = unsafe { Lazy::new(stdin_init) }; + static INSTANCE: Lazy>>> = Lazy::new(); return Stdin { - inner: INSTANCE.get().expect("cannot access stdin during shutdown"), + inner: unsafe { + INSTANCE.get(stdin_init).expect("cannot access stdin during shutdown") + }, }; fn stdin_init() -> Arc>>> { @@ -396,10 +398,11 @@ pub struct StdoutLock<'a> { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn stdout() -> Stdout { - static INSTANCE: Lazy>>>> - = unsafe { Lazy::new(stdout_init) }; + static INSTANCE: Lazy>>>> = Lazy::new(); return Stdout { - inner: INSTANCE.get().expect("cannot access stdout during shutdown"), + inner: unsafe { + INSTANCE.get(stdout_init).expect("cannot access stdout during shutdown") + }, }; fn stdout_init() -> Arc>>>> { @@ -533,10 +536,11 @@ pub struct StderrLock<'a> { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn stderr() -> Stderr { - static INSTANCE: Lazy>>> = - unsafe { Lazy::new(stderr_init) }; + static INSTANCE: Lazy>>> = Lazy::new(); return Stderr { - inner: INSTANCE.get().expect("cannot access stderr during shutdown"), + inner: unsafe { + INSTANCE.get(stderr_init).expect("cannot access stderr during shutdown") + }, }; fn stderr_init() -> Arc>>> { -- cgit 1.4.1-3-g733a5