// Copyright 2016 lazy-static.rs Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// 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;

use self::std::prelude::v1::*;
use self::std::sync::Once;
pub use self::std::sync::ONCE_INIT;

pub struct Lazy<T: Sync>(pub *const T, pub Once);

impl<T: Sync> Lazy<T> {
    #[inline(always)]
    pub fn get<F>(&'static mut self, f: F) -> &T
        where F: FnOnce() -> T
    {
        unsafe {
            let r = &mut self.0;
            self.1.call_once(|| {
                *r = Box::into_raw(Box::new(f()));
            });

            &*self.0
        }
    }
}

unsafe impl<T: Sync> Sync for Lazy<T> {}

#[macro_export]
#[doc(hidden)]
macro_rules! __lazy_static_create {
    ($NAME:ident, $T:ty) => {
        static mut $NAME: $crate::lazy::Lazy<$T> = $crate::lazy::Lazy(0 as *const $T, $crate::lazy::ONCE_INIT);
    }
}

// Copyright 2016 lazy-static.rs Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// 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;

use self::std::prelude::v1::*;
use self::std::sync::Once;
pub use self::std::sync::ONCE_INIT;

pub struct Lazy<T: Sync>(*const T, Once);

impl<T: Sync> Lazy<T> {
    pub const INIT: Self = Lazy(0 as *const T, ONCE_INIT);

    #[inline(always)]
    pub fn get<F>(&'static mut self, f: F) -> &T
    where
        F: FnOnce() -> T,
    {
        unsafe {
            let r = &mut self.0;
            self.1.call_once(|| {
                *r = Box::into_raw(Box::new(f()));
            });

            &*self.0
        }
    }
}

unsafe impl<T: Sync> Sync for Lazy<T> {}

#[macro_export]
#[doc(hidden)]
macro_rules! __lazy_static_create {
    ($NAME:ident, $T:ty) => {
        static mut $NAME: $crate::lazy::Lazy<$T> = $crate::lazy::Lazy::INIT;
    };
}

Use associated constant to make Lazy's fields private.
Use associated constant to make Lazy's fields private.

This is to patch an obscure soundness hole.

With the fields public, it is possible to for a consumer crate to access and call the std::sync::Once without assigning the correct value to the pointer in the tuple's first field, making it possible to later deref a null pointer from safe code.

However now that lazy_static targets 1.21.0+, we can use an associated constant in the __lazy_static_create macro instead of requiring consumers to literally construct the inner values post-expansion. This is technically a breaking change, but given that any existing use of these inner fields is very likely to cause unsoundness I think it's consistent with Rust's semver policy to make this change and stay at 1.0.
