<commit_before>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.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.

use rustc::middle::allocator::AllocatorKind;
use rustc_errors;
use syntax::{
    ast::{
        self, Arg, Attribute, Crate, Expr, FnHeader, Generics, Ident, Item, ItemKind,
        LitKind, Mac, Mod, Mutability, StrStyle, Ty, TyKind, Unsafety, VisibilityKind,
    },
    attr,
    codemap::{
        respan, ExpnInfo, MacroAttribute,
    },
    ext::{
        base::{ExtCtxt, Resolver},
        build::AstBuilder,
        expand::ExpansionConfig,
        hygiene::{self, Mark, SyntaxContext},
    },
    fold::{self, Folder},
    parse::ParseSess,
    ptr::P,
    symbol::Symbol,
    util::small_vector::SmallVector,
};
use syntax_pos::Span;

use {AllocatorMethod, AllocatorTy, ALLOCATOR_METHODS};

pub fn modify(
    sess: &ParseSess,
    resolver: &mut Resolver,
    krate: Crate,
    crate_name: String,
    handler: &rustc_errors::Handler,
) -> ast::Crate {
    ExpandAllocatorDirectives {
        handler,
        sess,
        resolver,
        found: false,
        crate_name: Some(crate_name),
        in_submod: -1, // -1 to account for the "root" module
    }.fold_crate(krate)
}

struct ExpandAllocatorDirectives<'a> {
    found: bool,
    handler: &'a rustc_errors::Handler,
    sess: &'a ParseSess,
    resolver: &'a mut Resolver,
    crate_name: Option<String>,

    // For now, we disallow `global_allocator` in submodules because hygiene is hard. Keep track of
    // whether we are in a submodule or not. If `in_submod > 0` we are in a submodule.
    in_submod: isize,
}

impl<'a> Folder for ExpandAllocatorDirectives<'a> {
    fn fold_item(&mut self, item: P<Item>) -> SmallVector<P<Item>> {
        info!("in submodule {}", self.in_submod);

        let name = if attr::contains_name(&item.attrs, "global_allocator") {
            "global_allocator"
        } else {
            return fold::noop_fold_item(item, self);
        };
        match item.node {
            ItemKind::Static(..) => {}
            _ => {
                self.handler
                    .span_err(item.span, "allocators must be statics");
                return SmallVector::one(item);
            }
        }

        if self.in_submod > 0 {
            self.handler
                .span_err(item.span, "`global_allocator` cannot be used in submodules");
            return SmallVector::one(item);
        }

        if self.found {
            self.handler
                .span_err(item.span, "cannot define more than one #[global_allocator]");
            return SmallVector::one(item);
        }
        self.found = true;

        // Create a fresh Mark for the new macro expansion we are about to do
        let mark = Mark::fresh(Mark::root());
        mark.set_expn_info(ExpnInfo {
            call_site: item.span, // use the call site of the static
            def_site: None,
            format: MacroAttribute(Symbol::intern(name)),
            allow_internal_unstable: true,
            allow_internal_unsafe: false,
            edition: hygiene::default_edition(),
        });

        // Tie the span to the macro expansion info we just created
        let span = item.span.with_ctxt(SyntaxContext::empty().apply_mark(mark));

        // Create an expansion config
        let ecfg = ExpansionConfig::default(self.crate_name.take().unwrap());

        // Generate a bunch of new items using the AllocFnFactory
        let mut f = AllocFnFactory {
            span,
            kind: AllocatorKind::Global,
            global: item.ident,
            core: Ident::from_str("core"),
            cx: ExtCtxt::new(self.sess, ecfg, self.resolver),
        };

        // We will generate a new submodule. To `use` the static from that module, we need to get
        // the `super::...` path.
        let super_path = f.cx.path(f.span, vec![Ident::from_str("super"), f.global]);

        // Generate the items in the submodule
        let mut items = vec![
            // import `core` to use allocators
            f.cx.item_extern_crate(f.span, f.core),
            // `use` the `global_allocator` in `super`
            f.cx.item_use_simple(
                f.span,
                respan(f.span.shrink_to_lo(), VisibilityKind::Inherited),
                super_path,
            ),
        ];

        // Add the allocator methods to the submodule
        items.extend(
            ALLOCATOR_METHODS
                .iter()
                .map(|method| f.allocator_fn(method)),
        );

        // Generate the submodule itself
        let name = f.kind.fn_name("allocator_abi");
        let allocator_abi = Ident::with_empty_ctxt(Symbol::gensym(&name));
        let module = f.cx.item_mod(span, span, allocator_abi, Vec::new(), items);
        let module = f.cx.monotonic_expander().fold_item(module).pop().unwrap();

        // Return the item and new submodule
        let mut ret = SmallVector::with_capacity(2);
        ret.push(item);
        ret.push(module);

        return ret;
    }

    // If we enter a submodule, take note.
    fn fold_mod(&mut self, m: Mod) -> Mod {
        info!("enter submodule");
        self.in_submod += 1;
        let ret = fold::noop_fold_mod(m, self);
        self.in_submod -= 1;
        info!("exit submodule");
        ret
    }

    // `fold_mac` is disabled by default. Enable it here.
    fn fold_mac(&mut self, mac: Mac) -> Mac {
        fold::noop_fold_mac(mac, self)
    }
}

struct AllocFnFactory<'a> {
    span: Span,
    kind: AllocatorKind,
    global: Ident,
    core: Ident,
    cx: ExtCtxt<'a>,
}

impl<'a> AllocFnFactory<'a> {
    fn allocator_fn(&self, method: &AllocatorMethod) -> P<Item> {
        let mut abi_args = Vec::new();
        let mut i = 0;
        let ref mut mk = || {
            let name = Ident::from_str(&format!("arg{}", i));
            i += 1;
            name
        };
        let args = method
            .inputs
            .iter()
            .map(|ty| self.arg_ty(ty, &mut abi_args, mk))
            .collect();
        let result = self.call_allocator(method.name, args);
        let (output_ty, output_expr) = self.ret_ty(&method.output, result);
        let kind = ItemKind::Fn(
            self.cx.fn_decl(abi_args, ast::FunctionRetTy::Ty(output_ty)),
            FnHeader {
                unsafety: Unsafety::Unsafe,
                ..FnHeader::default()
            },
            Generics::default(),
            self.cx.block_expr(output_expr),
        );
        self.cx.item(
            self.span,
            Ident::from_str(&self.kind.fn_name(method.name)),
            self.attrs(),
            kind,
        )
    }

    fn call_allocator(&self, method: &str, mut args: Vec<P<Expr>>) -> P<Expr> {
        let method = self.cx.path(
            self.span,
            vec![
                self.core,
                Ident::from_str("alloc"),
                Ident::from_str("GlobalAlloc"),
                Ident::from_str(method),
            ],
        );
        let method = self.cx.expr_path(method);
        let allocator = self.cx.path_ident(self.span, self.global);
        let allocator = self.cx.expr_path(allocator);
        let allocator = self.cx.expr_addr_of(self.span, allocator);
        args.insert(0, allocator);

        self.cx.expr_call(self.span, method, args)
    }

    fn attrs(&self) -> Vec<Attribute> {
        let key = Symbol::intern("linkage");
        let value = LitKind::Str(Symbol::intern("external"), StrStyle::Cooked);
        let linkage = self.cx.meta_name_value(self.span, key, value);

        let no_mangle = Symbol::intern("no_mangle");
        let no_mangle = self.cx.meta_word(self.span, no_mangle);

        let special = Symbol::intern("rustc_std_internal_symbol");
        let special = self.cx.meta_word(self.span, special);
        vec![
            self.cx.attribute(self.span, linkage),
            self.cx.attribute(self.span, no_mangle),
            self.cx.attribute(self.span, special),
        ]
    }

    fn arg_ty(
        &self,
        ty: &AllocatorTy,
        args: &mut Vec<Arg>,
        ident: &mut FnMut() -> Ident,
    ) -> P<Expr> {
        match *ty {
            AllocatorTy::Layout => {
                let usize = self.cx.path_ident(self.span, Ident::from_str("usize"));
                let ty_usize = self.cx.ty_path(usize);
                let size = ident();
                let align = ident();
                args.push(self.cx.arg(self.span, size, ty_usize.clone()));
                args.push(self.cx.arg(self.span, align, ty_usize));

                let layout_new = self.cx.path(
                    self.span,
                    vec![
                        self.core,
                        Ident::from_str("alloc"),
                        Ident::from_str("Layout"),
                        Ident::from_str("from_size_align_unchecked"),
                    ],
                );
                let layout_new = self.cx.expr_path(layout_new);
                let size = self.cx.expr_ident(self.span, size);
                let align = self.cx.expr_ident(self.span, align);
                let layout = self.cx.expr_call(self.span, layout_new, vec![size, align]);
                layout
            }

            AllocatorTy::Ptr => {
                let ident = ident();
                args.push(self.cx.arg(self.span, ident, self.ptr_u8()));
                let arg = self.cx.expr_ident(self.span, ident);
                self.cx.expr_cast(self.span, arg, self.ptr_u8())
            }

            AllocatorTy::Usize => {
                let ident = ident();
                args.push(self.cx.arg(self.span, ident, self.usize()));
                self.cx.expr_ident(self.span, ident)
            }

            AllocatorTy::ResultPtr | AllocatorTy::Unit => {
                panic!("can't convert AllocatorTy to an argument")
            }
        }
    }

    fn ret_ty(&self, ty: &AllocatorTy, expr: P<Expr>) -> (P<Ty>, P<Expr>) {
        match *ty {
            AllocatorTy::ResultPtr => {
                // We're creating:
                //
                //      #expr as *mut u8

                let expr = self.cx.expr_cast(self.span, expr, self.ptr_u8());
                (self.ptr_u8(), expr)
            }

            AllocatorTy::Unit => (self.cx.ty(self.span, TyKind::Tup(Vec::new())), expr),

            AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => {
                panic!("can't convert AllocatorTy to an output")
            }
        }
    }

    fn usize(&self) -> P<Ty> {
        let usize = self.cx.path_ident(self.span, Ident::from_str("usize"));
        self.cx.ty_path(usize)
    }

    fn ptr_u8(&self) -> P<Ty> {
        let u8 = self.cx.path_ident(self.span, Ident::from_str("u8"));
        let ty_u8 = self.cx.ty_path(u8);
        self.cx.ty_ptr(self.span, ty_u8, Mutability::Mutable)
    }
}
<commit_msg>used debug, not info<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.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.

use rustc::middle::allocator::AllocatorKind;
use rustc_errors;
use syntax::{
    ast::{
        self, Arg, Attribute, Crate, Expr, FnHeader, Generics, Ident, Item, ItemKind,
        LitKind, Mac, Mod, Mutability, StrStyle, Ty, TyKind, Unsafety, VisibilityKind,
    },
    attr,
    codemap::{
        respan, ExpnInfo, MacroAttribute,
    },
    ext::{
        base::{ExtCtxt, Resolver},
        build::AstBuilder,
        expand::ExpansionConfig,
        hygiene::{self, Mark, SyntaxContext},
    },
    fold::{self, Folder},
    parse::ParseSess,
    ptr::P,
    symbol::Symbol,
    util::small_vector::SmallVector,
};
use syntax_pos::Span;

use {AllocatorMethod, AllocatorTy, ALLOCATOR_METHODS};

pub fn modify(
    sess: &ParseSess,
    resolver: &mut Resolver,
    krate: Crate,
    crate_name: String,
    handler: &rustc_errors::Handler,
) -> ast::Crate {
    ExpandAllocatorDirectives {
        handler,
        sess,
        resolver,
        found: false,
        crate_name: Some(crate_name),
        in_submod: -1, // -1 to account for the "root" module
    }.fold_crate(krate)
}

struct ExpandAllocatorDirectives<'a> {
    found: bool,
    handler: &'a rustc_errors::Handler,
    sess: &'a ParseSess,
    resolver: &'a mut Resolver,
    crate_name: Option<String>,

    // For now, we disallow `global_allocator` in submodules because hygiene is hard. Keep track of
    // whether we are in a submodule or not. If `in_submod > 0` we are in a submodule.
    in_submod: isize,
}

impl<'a> Folder for ExpandAllocatorDirectives<'a> {
    fn fold_item(&mut self, item: P<Item>) -> SmallVector<P<Item>> {
        debug!("in submodule {}", self.in_submod);

        let name = if attr::contains_name(&item.attrs, "global_allocator") {
            "global_allocator"
        } else {
            return fold::noop_fold_item(item, self);
        };
        match item.node {
            ItemKind::Static(..) => {}
            _ => {
                self.handler
                    .span_err(item.span, "allocators must be statics");
                return SmallVector::one(item);
            }
        }

        if self.in_submod > 0 {
            self.handler
                .span_err(item.span, "`global_allocator` cannot be used in submodules");
            return SmallVector::one(item);
        }

        if self.found {
            self.handler
                .span_err(item.span, "cannot define more than one #[global_allocator]");
            return SmallVector::one(item);
        }
        self.found = true;

        // Create a fresh Mark for the new macro expansion we are about to do
        let mark = Mark::fresh(Mark::root());
        mark.set_expn_info(ExpnInfo {
            call_site: item.span, // use the call site of the static
            def_site: None,
            format: MacroAttribute(Symbol::intern(name)),
            allow_internal_unstable: true,
            allow_internal_unsafe: false,
            edition: hygiene::default_edition(),
        });

        // Tie the span to the macro expansion info we just created
        let span = item.span.with_ctxt(SyntaxContext::empty().apply_mark(mark));

        // Create an expansion config
        let ecfg = ExpansionConfig::default(self.crate_name.take().unwrap());

        // Generate a bunch of new items using the AllocFnFactory
        let mut f = AllocFnFactory {
            span,
            kind: AllocatorKind::Global,
            global: item.ident,
            core: Ident::from_str("core"),
            cx: ExtCtxt::new(self.sess, ecfg, self.resolver),
        };

        // We will generate a new submodule. To `use` the static from that module, we need to get
        // the `super::...` path.
        let super_path = f.cx.path(f.span, vec![Ident::from_str("super"), f.global]);

        // Generate the items in the submodule
        let mut items = vec![
            // import `core` to use allocators
            f.cx.item_extern_crate(f.span, f.core),
            // `use` the `global_allocator` in `super`
            f.cx.item_use_simple(
                f.span,
                respan(f.span.shrink_to_lo(), VisibilityKind::Inherited),
                super_path,
            ),
        ];

        // Add the allocator methods to the submodule
        items.extend(
            ALLOCATOR_METHODS
                .iter()
                .map(|method| f.allocator_fn(method)),
        );

        // Generate the submodule itself
        let name = f.kind.fn_name("allocator_abi");
        let allocator_abi = Ident::with_empty_ctxt(Symbol::gensym(&name));
        let module = f.cx.item_mod(span, span, allocator_abi, Vec::new(), items);
        let module = f.cx.monotonic_expander().fold_item(module).pop().unwrap();

        // Return the item and new submodule
        let mut ret = SmallVector::with_capacity(2);
        ret.push(item);
        ret.push(module);

        return ret;
    }

    // If we enter a submodule, take note.
    fn fold_mod(&mut self, m: Mod) -> Mod {
        debug!("enter submodule");
        self.in_submod += 1;
        let ret = fold::noop_fold_mod(m, self);
        self.in_submod -= 1;
        debug!("exit submodule");
        ret
    }

    // `fold_mac` is disabled by default. Enable it here.
    fn fold_mac(&mut self, mac: Mac) -> Mac {
        fold::noop_fold_mac(mac, self)
    }
}

struct AllocFnFactory<'a> {
    span: Span,
    kind: AllocatorKind,
    global: Ident,
    core: Ident,
    cx: ExtCtxt<'a>,
}

impl<'a> AllocFnFactory<'a> {
    fn allocator_fn(&self, method: &AllocatorMethod) -> P<Item> {
        let mut abi_args = Vec::new();
        let mut i = 0;
        let ref mut mk = || {
            let name = Ident::from_str(&format!("arg{}", i));
            i += 1;
            name
        };
        let args = method
            .inputs
            .iter()
            .map(|ty| self.arg_ty(ty, &mut abi_args, mk))
            .collect();
        let result = self.call_allocator(method.name, args);
        let (output_ty, output_expr) = self.ret_ty(&method.output, result);
        let kind = ItemKind::Fn(
            self.cx.fn_decl(abi_args, ast::FunctionRetTy::Ty(output_ty)),
            FnHeader {
                unsafety: Unsafety::Unsafe,
                ..FnHeader::default()
            },
            Generics::default(),
            self.cx.block_expr(output_expr),
        );
        self.cx.item(
            self.span,
            Ident::from_str(&self.kind.fn_name(method.name)),
            self.attrs(),
            kind,
        )
    }

    fn call_allocator(&self, method: &str, mut args: Vec<P<Expr>>) -> P<Expr> {
        let method = self.cx.path(
            self.span,
            vec![
                self.core,
                Ident::from_str("alloc"),
                Ident::from_str("GlobalAlloc"),
                Ident::from_str(method),
            ],
        );
        let method = self.cx.expr_path(method);
        let allocator = self.cx.path_ident(self.span, self.global);
        let allocator = self.cx.expr_path(allocator);
        let allocator = self.cx.expr_addr_of(self.span, allocator);
        args.insert(0, allocator);

        self.cx.expr_call(self.span, method, args)
    }

    fn attrs(&self) -> Vec<Attribute> {
        let key = Symbol::intern("linkage");
        let value = LitKind::Str(Symbol::intern("external"), StrStyle::Cooked);
        let linkage = self.cx.meta_name_value(self.span, key, value);

        let no_mangle = Symbol::intern("no_mangle");
        let no_mangle = self.cx.meta_word(self.span, no_mangle);

        let special = Symbol::intern("rustc_std_internal_symbol");
        let special = self.cx.meta_word(self.span, special);
        vec![
            self.cx.attribute(self.span, linkage),
            self.cx.attribute(self.span, no_mangle),
            self.cx.attribute(self.span, special),
        ]
    }

    fn arg_ty(
        &self,
        ty: &AllocatorTy,
        args: &mut Vec<Arg>,
        ident: &mut FnMut() -> Ident,
    ) -> P<Expr> {
        match *ty {
            AllocatorTy::Layout => {
                let usize = self.cx.path_ident(self.span, Ident::from_str("usize"));
                let ty_usize = self.cx.ty_path(usize);
                let size = ident();
                let align = ident();
                args.push(self.cx.arg(self.span, size, ty_usize.clone()));
                args.push(self.cx.arg(self.span, align, ty_usize));

                let layout_new = self.cx.path(
                    self.span,
                    vec![
                        self.core,
                        Ident::from_str("alloc"),
                        Ident::from_str("Layout"),
                        Ident::from_str("from_size_align_unchecked"),
                    ],
                );
                let layout_new = self.cx.expr_path(layout_new);
                let size = self.cx.expr_ident(self.span, size);
                let align = self.cx.expr_ident(self.span, align);
                let layout = self.cx.expr_call(self.span, layout_new, vec![size, align]);
                layout
            }

            AllocatorTy::Ptr => {
                let ident = ident();
                args.push(self.cx.arg(self.span, ident, self.ptr_u8()));
                let arg = self.cx.expr_ident(self.span, ident);
                self.cx.expr_cast(self.span, arg, self.ptr_u8())
            }

            AllocatorTy::Usize => {
                let ident = ident();
                args.push(self.cx.arg(self.span, ident, self.usize()));
                self.cx.expr_ident(self.span, ident)
            }

            AllocatorTy::ResultPtr | AllocatorTy::Unit => {
                panic!("can't convert AllocatorTy to an argument")
            }
        }
    }

    fn ret_ty(&self, ty: &AllocatorTy, expr: P<Expr>) -> (P<Ty>, P<Expr>) {
        match *ty {
            AllocatorTy::ResultPtr => {
                // We're creating:
                //
                //      #expr as *mut u8

                let expr = self.cx.expr_cast(self.span, expr, self.ptr_u8());
                (self.ptr_u8(), expr)
            }

            AllocatorTy::Unit => (self.cx.ty(self.span, TyKind::Tup(Vec::new())), expr),

            AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => {
                panic!("can't convert AllocatorTy to an output")
            }
        }
    }

    fn usize(&self) -> P<Ty> {
        let usize = self.cx.path_ident(self.span, Ident::from_str("usize"));
        self.cx.ty_path(usize)
    }

    fn ptr_u8(&self) -> P<Ty> {
        let u8 = self.cx.path_ident(self.span, Ident::from_str("u8"));
        let ty_u8 = self.cx.ty_path(u8);
        self.cx.ty_ptr(self.span, ty_u8, Mutability::Mutable)
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.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.
#![unstable(feature = "reentrant_mutex", reason = "new API")]

use prelude::v1::*;

use fmt;
use marker;
use ops::Deref;
use sys_common::poison::{self, TryLockError, TryLockResult, LockResult};
use sys::mutex as sys;

/// A re-entrant mutual exclusion
///
/// This mutex will block *other* threads waiting for the lock to become
/// available. The thread which has already locked the mutex can lock it
/// multiple times without blocking, preventing a common source of deadlocks.
pub struct ReentrantMutex<T> {
    inner: Box<sys::ReentrantMutex>,
    poison: poison::Flag,
    data: T,
}

unsafe impl<T: Send> Send for ReentrantMutex<T> {}
unsafe impl<T: Send> Sync for ReentrantMutex<T> {}

/// An RAII implementation of a "scoped lock" of a mutex. When this structure is
/// dropped (falls out of scope), the lock will be unlocked.
///
/// The data protected by the mutex can be accessed through this guard via its
/// Deref and DerefMut implementations
#[must_use]
pub struct ReentrantMutexGuard<'a, T: 'a> {
    // funny underscores due to how Deref/DerefMut currently work (they
    // disregard field privacy).
    __lock: &'a ReentrantMutex<T>,
    __poison: poison::Guard,
}

impl<'a, T> !marker::Send for ReentrantMutexGuard<'a, T> {}

impl<T> ReentrantMutex<T> {
    /// Creates a new reentrant mutex in an unlocked state.
    pub fn new(t: T) -> ReentrantMutex<T> {
        unsafe {
            let mut mutex = ReentrantMutex {
                inner: box sys::ReentrantMutex::uninitialized(),
                poison: poison::Flag::new(),
                data: t,
            };
            mutex.inner.init();
            return mutex
        }
    }

    /// Acquires a mutex, blocking the current thread until it is able to do so.
    ///
    /// This function will block the caller until it is available to acquire the mutex.
    /// Upon returning, the thread is the only thread with the mutex held. When the thread
    /// calling this method already holds the lock, the call shall succeed without
    /// blocking.
    ///
    /// # Failure
    ///
    /// If another user of this mutex panicked while holding the mutex, then
    /// this call will return failure if the mutex would otherwise be
    /// acquired.
    pub fn lock(&self) -> LockResult<ReentrantMutexGuard<T>> {
        unsafe { self.inner.lock() }
        ReentrantMutexGuard::new(&self)
    }

    /// Attempts to acquire this lock.
    ///
    /// If the lock could not be acquired at this time, then `Err` is returned.
    /// Otherwise, an RAII guard is returned.
    ///
    /// This function does not block.
    ///
    /// # Failure
    ///
    /// If another user of this mutex panicked while holding the mutex, then
    /// this call will return failure if the mutex would otherwise be
    /// acquired.
    pub fn try_lock(&self) -> TryLockResult<ReentrantMutexGuard<T>> {
        if unsafe { self.inner.try_lock() } {
            Ok(try!(ReentrantMutexGuard::new(&self)))
        } else {
            Err(TryLockError::WouldBlock)
        }
    }
}

impl<T> Drop for ReentrantMutex<T> {
    fn drop(&mut self) {
        // This is actually safe b/c we know that there is no further usage of
        // this mutex (it's up to the user to arrange for a mutex to get
        // dropped, that's not our job)
        unsafe { self.inner.destroy() }
    }
}

impl<T: fmt::Debug + 'static> fmt::Debug for ReentrantMutex<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.try_lock() {
            Ok(guard) => write!(f, "ReentrantMutex {{ data: {:?} }}", &*guard),
            Err(TryLockError::Poisoned(err)) => {
                write!(f, "ReentrantMutex {{ data: Poisoned({:?}) }}", &**err.get_ref())
            },
            Err(TryLockError::WouldBlock) => write!(f, "ReentrantMutex {{ <locked> }}")
        }
    }
}

impl<'mutex, T> ReentrantMutexGuard<'mutex, T> {
    fn new(lock: &'mutex ReentrantMutex<T>)
            -> LockResult<ReentrantMutexGuard<'mutex, T>> {
        poison::map_result(lock.poison.borrow(), |guard| {
            ReentrantMutexGuard {
                __lock: lock,
                __poison: guard,
            }
        })
    }
}

impl<'mutex, T> Deref for ReentrantMutexGuard<'mutex, T> {
    type Target = T;

    fn deref<'a>(&'a self) -> &'a T {
        &self.__lock.data
    }
}

impl<'a, T> Drop for ReentrantMutexGuard<'a, T> {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            self.__lock.poison.done(&self.__poison);
            self.__lock.inner.unlock();
        }
    }
}

#[cfg(test)]
mod tests {
    use prelude::v1::*;
    use sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard};
    use cell::RefCell;
    use sync::Arc;
    use boxed;
    use thread;

    #[test]
    fn smoke() {
        let m = ReentrantMutex::new(());
        {
            let a = m.lock().unwrap();
            {
                let b = m.lock().unwrap();
                {
                    let c = m.lock().unwrap();
                    assert_eq!(*c, ());
                }
                assert_eq!(*b, ());
            }
            assert_eq!(*a, ());
        }
    }

    #[test]
    fn is_mutex() {
        let m = ReentrantMutex::new(RefCell::new(0));
        let lock = m.lock().unwrap();
        let handle = thread::scoped(|| {
            let lock = m.lock().unwrap();
            assert_eq!(*lock.borrow(), 4950);
        });
        for i in 0..100 {
            let lock = m.lock().unwrap();
            *lock.borrow_mut() += i;
        }
        drop(lock);
        drop(handle);
    }

    #[test]
    fn trylock_works() {
        let m = ReentrantMutex::new(());
        let lock = m.try_lock().unwrap();
        let lock2 = m.try_lock().unwrap();
        {
            thread::scoped(|| {
                let lock = m.try_lock();
                assert!(lock.is_err());
            });
        }
        let lock3 = m.try_lock().unwrap();
    }

    pub struct Answer<'a>(pub ReentrantMutexGuard<'a, RefCell<u32>>);
    impl<'a> Drop for Answer<'a> {
        fn drop(&mut self) {
            *self.0.borrow_mut() = 42;
        }
    }

    #[test]
    fn poison_works() {
        let m = Arc::new(ReentrantMutex::new(RefCell::new(0)));
        let mc = m.clone();
        let result = thread::spawn(move ||{
            let lock = mc.lock().unwrap();
            *lock.borrow_mut() = 1;
            let lock2 = mc.lock().unwrap();
            *lock.borrow_mut() = 2;
            let answer = Answer(lock2);
            panic!("What the answer to my lifetimes dilemma is?");
            drop(answer);
        }).join();
        assert!(result.is_err());
        let r = m.lock().err().unwrap().into_inner();
        assert_eq!(*r.borrow(), 42);
    }
}
<commit_msg>Auto merge of #27693 - nagisa:remutex-docs, r=alexcrichton<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.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.
#![unstable(feature = "reentrant_mutex", reason = "new API")]

use prelude::v1::*;

use fmt;
use marker;
use ops::Deref;
use sys_common::poison::{self, TryLockError, TryLockResult, LockResult};
use sys::mutex as sys;

/// A re-entrant mutual exclusion
///
/// This mutex will block *other* threads waiting for the lock to become
/// available. The thread which has already locked the mutex can lock it
/// multiple times without blocking, preventing a common source of deadlocks.
pub struct ReentrantMutex<T> {
    inner: Box<sys::ReentrantMutex>,
    poison: poison::Flag,
    data: T,
}

unsafe impl<T: Send> Send for ReentrantMutex<T> {}
unsafe impl<T: Send> Sync for ReentrantMutex<T> {}

/// An RAII implementation of a "scoped lock" of a mutex. When this structure is
/// dropped (falls out of scope), the lock will be unlocked.
///
/// The data protected by the mutex can be accessed through this guard via its
/// Deref implementation.
///
/// # Mutability
///
/// Unlike `MutexGuard`, `ReentrantMutexGuard` does not implement `DerefMut`,
/// because implementation of the trait would violate Rust’s reference aliasing
/// rules. Use interior mutability (usually `RefCell`) in order to mutate the
/// guarded data.
#[must_use]
pub struct ReentrantMutexGuard<'a, T: 'a> {
    // funny underscores due to how Deref currently works (it disregards field
    // privacy).
    __lock: &'a ReentrantMutex<T>,
    __poison: poison::Guard,
}

impl<'a, T> !marker::Send for ReentrantMutexGuard<'a, T> {}

impl<T> ReentrantMutex<T> {
    /// Creates a new reentrant mutex in an unlocked state.
    pub fn new(t: T) -> ReentrantMutex<T> {
        unsafe {
            let mut mutex = ReentrantMutex {
                inner: box sys::ReentrantMutex::uninitialized(),
                poison: poison::Flag::new(),
                data: t,
            };
            mutex.inner.init();
            return mutex
        }
    }

    /// Acquires a mutex, blocking the current thread until it is able to do so.
    ///
    /// This function will block the caller until it is available to acquire the mutex.
    /// Upon returning, the thread is the only thread with the mutex held. When the thread
    /// calling this method already holds the lock, the call shall succeed without
    /// blocking.
    ///
    /// # Failure
    ///
    /// If another user of this mutex panicked while holding the mutex, then
    /// this call will return failure if the mutex would otherwise be
    /// acquired.
    pub fn lock(&self) -> LockResult<ReentrantMutexGuard<T>> {
        unsafe { self.inner.lock() }
        ReentrantMutexGuard::new(&self)
    }

    /// Attempts to acquire this lock.
    ///
    /// If the lock could not be acquired at this time, then `Err` is returned.
    /// Otherwise, an RAII guard is returned.
    ///
    /// This function does not block.
    ///
    /// # Failure
    ///
    /// If another user of this mutex panicked while holding the mutex, then
    /// this call will return failure if the mutex would otherwise be
    /// acquired.
    pub fn try_lock(&self) -> TryLockResult<ReentrantMutexGuard<T>> {
        if unsafe { self.inner.try_lock() } {
            Ok(try!(ReentrantMutexGuard::new(&self)))
        } else {
            Err(TryLockError::WouldBlock)
        }
    }
}

impl<T> Drop for ReentrantMutex<T> {
    fn drop(&mut self) {
        // This is actually safe b/c we know that there is no further usage of
        // this mutex (it's up to the user to arrange for a mutex to get
        // dropped, that's not our job)
        unsafe { self.inner.destroy() }
    }
}

impl<T: fmt::Debug + 'static> fmt::Debug for ReentrantMutex<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.try_lock() {
            Ok(guard) => write!(f, "ReentrantMutex {{ data: {:?} }}", &*guard),
            Err(TryLockError::Poisoned(err)) => {
                write!(f, "ReentrantMutex {{ data: Poisoned({:?}) }}", &**err.get_ref())
            },
            Err(TryLockError::WouldBlock) => write!(f, "ReentrantMutex {{ <locked> }}")
        }
    }
}

impl<'mutex, T> ReentrantMutexGuard<'mutex, T> {
    fn new(lock: &'mutex ReentrantMutex<T>)
            -> LockResult<ReentrantMutexGuard<'mutex, T>> {
        poison::map_result(lock.poison.borrow(), |guard| {
            ReentrantMutexGuard {
                __lock: lock,
                __poison: guard,
            }
        })
    }
}

impl<'mutex, T> Deref for ReentrantMutexGuard<'mutex, T> {
    type Target = T;

    fn deref<'a>(&'a self) -> &'a T {
        &self.__lock.data
    }
}

impl<'a, T> Drop for ReentrantMutexGuard<'a, T> {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            self.__lock.poison.done(&self.__poison);
            self.__lock.inner.unlock();
        }
    }
}

#[cfg(test)]
mod tests {
    use prelude::v1::*;
    use sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard};
    use cell::RefCell;
    use sync::Arc;
    use boxed;
    use thread;

    #[test]
    fn smoke() {
        let m = ReentrantMutex::new(());
        {
            let a = m.lock().unwrap();
            {
                let b = m.lock().unwrap();
                {
                    let c = m.lock().unwrap();
                    assert_eq!(*c, ());
                }
                assert_eq!(*b, ());
            }
            assert_eq!(*a, ());
        }
    }

    #[test]
    fn is_mutex() {
        let m = ReentrantMutex::new(RefCell::new(0));
        let lock = m.lock().unwrap();
        let handle = thread::scoped(|| {
            let lock = m.lock().unwrap();
            assert_eq!(*lock.borrow(), 4950);
        });
        for i in 0..100 {
            let lock = m.lock().unwrap();
            *lock.borrow_mut() += i;
        }
        drop(lock);
        drop(handle);
    }

    #[test]
    fn trylock_works() {
        let m = ReentrantMutex::new(());
        let lock = m.try_lock().unwrap();
        let lock2 = m.try_lock().unwrap();
        {
            thread::scoped(|| {
                let lock = m.try_lock();
                assert!(lock.is_err());
            });
        }
        let lock3 = m.try_lock().unwrap();
    }

    pub struct Answer<'a>(pub ReentrantMutexGuard<'a, RefCell<u32>>);
    impl<'a> Drop for Answer<'a> {
        fn drop(&mut self) {
            *self.0.borrow_mut() = 42;
        }
    }

    #[test]
    fn poison_works() {
        let m = Arc::new(ReentrantMutex::new(RefCell::new(0)));
        let mc = m.clone();
        let result = thread::spawn(move ||{
            let lock = mc.lock().unwrap();
            *lock.borrow_mut() = 1;
            let lock2 = mc.lock().unwrap();
            *lock.borrow_mut() = 2;
            let answer = Answer(lock2);
            panic!("What the answer to my lifetimes dilemma is?");
            drop(answer);
        }).join();
        assert!(result.is_err());
        let r = m.lock().err().unwrap().into_inner();
        assert_eq!(*r.borrow(), 42);
    }
}
<|endoftext|>


<commit_before>use core::{
    fmt, mem,
    future::Future,
    marker::{PhantomData, Unpin},
    pin::Pin,
    task::{LocalWaker, Poll},
};

/// A custom trait object for polling futures, roughly akin to
/// `Box<dyn Future<Output = T> + 'a>`.
///
/// This custom trait object was introduced for two reasons:
/// - Currently it is not possible to take `dyn Trait` by value and
///   `Box<dyn Trait>` is not available in no_std contexts.
/// - The `Future` trait is currently not object safe: The `Future::poll`
///   method makes uses the arbitrary self types feature and traits in which
///   this feature is used are currently not object safe due to current compiler
///   limitations. (See tracking issue for arbitrary self types for more
///   information #44874)
pub struct LocalFutureObj<'a, T> {
    ptr: *mut (),
    poll_fn: unsafe fn(*mut (), &LocalWaker) -> Poll<T>,
    drop_fn: unsafe fn(*mut ()),
    _marker: PhantomData<&'a ()>,
}

impl<'a, T> Unpin for LocalFutureObj<'a, T> {}

impl<'a, T> LocalFutureObj<'a, T> {
    /// Create a `LocalFutureObj` from a custom trait object representation.
    #[inline]
    pub fn new<F: UnsafeFutureObj<'a, T> + 'a>(f: F) -> LocalFutureObj<'a, T> {
        LocalFutureObj {
            ptr: f.into_raw(),
            poll_fn: F::poll,
            drop_fn: F::drop,
            _marker: PhantomData,
        }
    }

    /// Converts the `LocalFutureObj` into a `FutureObj`
    /// To make this operation safe one has to ensure that the `UnsafeFutureObj`
    /// instance from which this `LocalFutureObj` was created actually
    /// implements `Send`.
    #[inline]
    pub unsafe fn into_future_obj(self) -> FutureObj<'a, T> {
        FutureObj(self)
    }
}

impl<'a, T> fmt::Debug for LocalFutureObj<'a, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("LocalFutureObj")
            .finish()
    }
}

impl<'a, T> From<FutureObj<'a, T>> for LocalFutureObj<'a, T> {
    #[inline]
    fn from(f: FutureObj<'a, T>) -> LocalFutureObj<'a, T> {
        f.0
    }
}

impl<'a, T> Future for LocalFutureObj<'a, T> {
    type Output = T;

    #[inline]
    fn poll(self: Pin<&mut Self>, lw: &LocalWaker) -> Poll<T> {
        unsafe {
            ((*self).poll_fn)((*self).ptr, lw)
        }
    }
}

impl<'a, T> Drop for LocalFutureObj<'a, T> {
    fn drop(&mut self) {
        unsafe {
            (self.drop_fn)(self.ptr)
        }
    }
}

/// A custom trait object for polling futures, roughly akin to
/// `Box<dyn Future<Output = T> + Send + 'a>`.
///
/// This custom trait object was introduced for two reasons:
/// - Currently it is not possible to take `dyn Trait` by value and
///   `Box<dyn Trait>` is not available in no_std contexts.
/// - The `Future` trait is currently not object safe: The `Future::poll`
///   method makes uses the arbitrary self types feature and traits in which
///   this feature is used are currently not object safe due to current compiler
///   limitations. (See tracking issue for arbitrary self types for more
///   information #44874)
pub struct FutureObj<'a, T>(LocalFutureObj<'a, T>);

impl<'a, T> Unpin for FutureObj<'a, T> {}
unsafe impl<'a, T> Send for FutureObj<'a, T> {}

impl<'a, T> FutureObj<'a, T> {
    /// Create a `FutureObj` from a custom trait object representation.
    #[inline]
    pub fn new<F: UnsafeFutureObj<'a, T> + Send>(f: F) -> FutureObj<'a, T> {
        FutureObj(LocalFutureObj::new(f))
    }
}

impl<'a, T> fmt::Debug for FutureObj<'a, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("FutureObj")
            .finish()
    }
}

impl<'a, T> Future for FutureObj<'a, T> {
    type Output = T;

    #[inline]
    fn poll(self: Pin<&mut Self>, lw: &LocalWaker) -> Poll<T> {
        let pinned_field: Pin<&mut LocalFutureObj<'a, T>> = unsafe {
            Pin::map_unchecked_mut(self, |x| &mut x.0)
        };
        LocalFutureObj::poll(pinned_field, lw)
    }
}

/// A custom implementation of a future trait object for `FutureObj`, providing
/// a hand-rolled vtable.
///
/// This custom representation is typically used only in `no_std` contexts,
/// where the default `Box`-based implementation is not available.
///
/// The implementor must guarantee that it is safe to call `poll` repeatedly (in
/// a non-concurrent fashion) with the result of `into_raw` until `drop` is
/// called.
pub unsafe trait UnsafeFutureObj<'a, T>: 'a {
    /// Convert an owned instance into a (conceptually owned) void pointer.
    fn into_raw(self) -> *mut ();

    /// Poll the future represented by the given void pointer.
    ///
    /// # Safety
    ///
    /// The trait implementor must guarantee that it is safe to repeatedly call
    /// `poll` with the result of `into_raw` until `drop` is called; such calls
    /// are not, however, allowed to race with each other or with calls to
    /// `drop`.
    unsafe fn poll(ptr: *mut (), lw: &LocalWaker) -> Poll<T>;

    /// Drops the future represented by the given void pointer.
    ///
    /// # Safety
    ///
    /// The trait implementor must guarantee that it is safe to call this
    /// function once per `into_raw` invocation; that call cannot race with
    /// other calls to `drop` or `poll`.
    unsafe fn drop(ptr: *mut ());
}

unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for &'a mut F
where
    F: Future<Output = T> + Unpin + 'a
{
    fn into_raw(self) -> *mut () {
        self as *mut F as *mut ()
    }

    unsafe fn poll(ptr: *mut (), lw: &LocalWaker) -> Poll<T> {
        let p: Pin<&mut F> = Pin::new_unchecked(&mut *(ptr as *mut F));
        F::poll(p, lw)
    }

    unsafe fn drop(_ptr: *mut ()) {}
}

unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for Pin<&'a mut F>
where
    F: Future<Output = T> + 'a
{
    fn into_raw(mut self) -> *mut () {
        let mut_ref: &mut F = unsafe { Pin::get_mut_unchecked(Pin::as_mut(&mut self)) };
        mut_ref as *mut F as *mut ()
    }

    unsafe fn poll(ptr: *mut (), lw: &LocalWaker) -> Poll<T> {
        let future: Pin<&mut F> = Pin::new_unchecked(&mut *(ptr as *mut F));
        F::poll(future, lw)
    }

    unsafe fn drop(_ptr: *mut ()) {}
}

if_std! {
    use std::boxed::Box;

    unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for Box<F>
        where F: Future<Output = T> + 'a
    {
        fn into_raw(self) -> *mut () {
            Box::into_raw(self) as *mut ()
        }

        unsafe fn poll(ptr: *mut (), lw: &LocalWaker) -> Poll<T> {
            let ptr = ptr as *mut F;
            let pin: Pin<&mut F> = Pin::new_unchecked(&mut *ptr);
            F::poll(pin, lw)
        }

        unsafe fn drop(ptr: *mut ()) {
            drop(Box::from_raw(ptr as *mut F))
        }
    }

    unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for Pin<Box<F>>
    where
        F: Future<Output = T> + 'a
    {
        fn into_raw(mut self) -> *mut () {
            let mut_ref: &mut F = unsafe { Pin::get_mut_unchecked(Pin::as_mut(&mut self)) };
            let ptr = mut_ref as *mut F as *mut ();
            mem::forget(self); // Don't drop the box
            ptr
        }

        unsafe fn poll(ptr: *mut (), lw: &LocalWaker) -> Poll<T> {
            let ptr = ptr as *mut F;
            let pin: Pin<&mut F> = Pin::new_unchecked(&mut *ptr);
            F::poll(pin, lw)
        }

        unsafe fn drop(ptr: *mut ()) {
            #[allow(clippy::cast_ptr_alignment)]
            drop(Box::from_raw(ptr as *mut Pin<Box<T>>));
        }
    }

    impl<'a, F: Future<Output = ()> + Send + 'a> From<Pin<Box<F>>> for FutureObj<'a, ()> {
        fn from(boxed: Pin<Box<F>>) -> Self {
            FutureObj::new(boxed)
        }
    }

    impl<'a, F: Future<Output = ()> + Send + 'a> From<Box<F>> for FutureObj<'a, ()> {
        fn from(boxed: Box<F>) -> Self {
            FutureObj::new(boxed)
        }
    }

    impl<'a, F: Future<Output = ()> + 'a> From<Pin<Box<F>>> for LocalFutureObj<'a, ()> {
        fn from(boxed: Pin<Box<F>>) -> Self {
            LocalFutureObj::new(boxed)
        }
    }

    impl<'a, F: Future<Output = ()> + 'a> From<Box<F>> for LocalFutureObj<'a, ()> {
        fn from(boxed: Box<F>) -> Self {
            LocalFutureObj::new(boxed)
        }
    }
}
<commit_msg>Fix an invalid cast in the impl of UnsafeFutureObj for Pin<Box<F>><commit_after>use core::{
    fmt, mem,
    future::Future,
    marker::{PhantomData, Unpin},
    pin::Pin,
    task::{LocalWaker, Poll},
};

/// A custom trait object for polling futures, roughly akin to
/// `Box<dyn Future<Output = T> + 'a>`.
///
/// This custom trait object was introduced for two reasons:
/// - Currently it is not possible to take `dyn Trait` by value and
///   `Box<dyn Trait>` is not available in no_std contexts.
/// - The `Future` trait is currently not object safe: The `Future::poll`
///   method makes uses the arbitrary self types feature and traits in which
///   this feature is used are currently not object safe due to current compiler
///   limitations. (See tracking issue for arbitrary self types for more
///   information #44874)
pub struct LocalFutureObj<'a, T> {
    ptr: *mut (),
    poll_fn: unsafe fn(*mut (), &LocalWaker) -> Poll<T>,
    drop_fn: unsafe fn(*mut ()),
    _marker: PhantomData<&'a ()>,
}

impl<'a, T> Unpin for LocalFutureObj<'a, T> {}

impl<'a, T> LocalFutureObj<'a, T> {
    /// Create a `LocalFutureObj` from a custom trait object representation.
    #[inline]
    pub fn new<F: UnsafeFutureObj<'a, T> + 'a>(f: F) -> LocalFutureObj<'a, T> {
        LocalFutureObj {
            ptr: f.into_raw(),
            poll_fn: F::poll,
            drop_fn: F::drop,
            _marker: PhantomData,
        }
    }

    /// Converts the `LocalFutureObj` into a `FutureObj`
    /// To make this operation safe one has to ensure that the `UnsafeFutureObj`
    /// instance from which this `LocalFutureObj` was created actually
    /// implements `Send`.
    #[inline]
    pub unsafe fn into_future_obj(self) -> FutureObj<'a, T> {
        FutureObj(self)
    }
}

impl<'a, T> fmt::Debug for LocalFutureObj<'a, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("LocalFutureObj")
            .finish()
    }
}

impl<'a, T> From<FutureObj<'a, T>> for LocalFutureObj<'a, T> {
    #[inline]
    fn from(f: FutureObj<'a, T>) -> LocalFutureObj<'a, T> {
        f.0
    }
}

impl<'a, T> Future for LocalFutureObj<'a, T> {
    type Output = T;

    #[inline]
    fn poll(self: Pin<&mut Self>, lw: &LocalWaker) -> Poll<T> {
        unsafe {
            ((*self).poll_fn)((*self).ptr, lw)
        }
    }
}

impl<'a, T> Drop for LocalFutureObj<'a, T> {
    fn drop(&mut self) {
        unsafe {
            (self.drop_fn)(self.ptr)
        }
    }
}

/// A custom trait object for polling futures, roughly akin to
/// `Box<dyn Future<Output = T> + Send + 'a>`.
///
/// This custom trait object was introduced for two reasons:
/// - Currently it is not possible to take `dyn Trait` by value and
///   `Box<dyn Trait>` is not available in no_std contexts.
/// - The `Future` trait is currently not object safe: The `Future::poll`
///   method makes uses the arbitrary self types feature and traits in which
///   this feature is used are currently not object safe due to current compiler
///   limitations. (See tracking issue for arbitrary self types for more
///   information #44874)
pub struct FutureObj<'a, T>(LocalFutureObj<'a, T>);

impl<'a, T> Unpin for FutureObj<'a, T> {}
unsafe impl<'a, T> Send for FutureObj<'a, T> {}

impl<'a, T> FutureObj<'a, T> {
    /// Create a `FutureObj` from a custom trait object representation.
    #[inline]
    pub fn new<F: UnsafeFutureObj<'a, T> + Send>(f: F) -> FutureObj<'a, T> {
        FutureObj(LocalFutureObj::new(f))
    }
}

impl<'a, T> fmt::Debug for FutureObj<'a, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("FutureObj")
            .finish()
    }
}

impl<'a, T> Future for FutureObj<'a, T> {
    type Output = T;

    #[inline]
    fn poll(self: Pin<&mut Self>, lw: &LocalWaker) -> Poll<T> {
        let pinned_field: Pin<&mut LocalFutureObj<'a, T>> = unsafe {
            Pin::map_unchecked_mut(self, |x| &mut x.0)
        };
        LocalFutureObj::poll(pinned_field, lw)
    }
}

/// A custom implementation of a future trait object for `FutureObj`, providing
/// a hand-rolled vtable.
///
/// This custom representation is typically used only in `no_std` contexts,
/// where the default `Box`-based implementation is not available.
///
/// The implementor must guarantee that it is safe to call `poll` repeatedly (in
/// a non-concurrent fashion) with the result of `into_raw` until `drop` is
/// called.
pub unsafe trait UnsafeFutureObj<'a, T>: 'a {
    /// Convert an owned instance into a (conceptually owned) void pointer.
    fn into_raw(self) -> *mut ();

    /// Poll the future represented by the given void pointer.
    ///
    /// # Safety
    ///
    /// The trait implementor must guarantee that it is safe to repeatedly call
    /// `poll` with the result of `into_raw` until `drop` is called; such calls
    /// are not, however, allowed to race with each other or with calls to
    /// `drop`.
    unsafe fn poll(ptr: *mut (), lw: &LocalWaker) -> Poll<T>;

    /// Drops the future represented by the given void pointer.
    ///
    /// # Safety
    ///
    /// The trait implementor must guarantee that it is safe to call this
    /// function once per `into_raw` invocation; that call cannot race with
    /// other calls to `drop` or `poll`.
    unsafe fn drop(ptr: *mut ());
}

unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for &'a mut F
where
    F: Future<Output = T> + Unpin + 'a
{
    fn into_raw(self) -> *mut () {
        self as *mut F as *mut ()
    }

    unsafe fn poll(ptr: *mut (), lw: &LocalWaker) -> Poll<T> {
        let p: Pin<&mut F> = Pin::new_unchecked(&mut *(ptr as *mut F));
        F::poll(p, lw)
    }

    unsafe fn drop(_ptr: *mut ()) {}
}

unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for Pin<&'a mut F>
where
    F: Future<Output = T> + 'a
{
    fn into_raw(mut self) -> *mut () {
        let mut_ref: &mut F = unsafe { Pin::get_mut_unchecked(Pin::as_mut(&mut self)) };
        mut_ref as *mut F as *mut ()
    }

    unsafe fn poll(ptr: *mut (), lw: &LocalWaker) -> Poll<T> {
        let future: Pin<&mut F> = Pin::new_unchecked(&mut *(ptr as *mut F));
        F::poll(future, lw)
    }

    unsafe fn drop(_ptr: *mut ()) {}
}

if_std! {
    use std::boxed::Box;

    unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for Box<F>
        where F: Future<Output = T> + 'a
    {
        fn into_raw(self) -> *mut () {
            Box::into_raw(self) as *mut ()
        }

        unsafe fn poll(ptr: *mut (), lw: &LocalWaker) -> Poll<T> {
            let ptr = ptr as *mut F;
            let pin: Pin<&mut F> = Pin::new_unchecked(&mut *ptr);
            F::poll(pin, lw)
        }

        unsafe fn drop(ptr: *mut ()) {
            drop(Box::from_raw(ptr as *mut F))
        }
    }

    unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for Pin<Box<F>>
    where
        F: Future<Output = T> + 'a
    {
        fn into_raw(mut self) -> *mut () {
            let mut_ref: &mut F = unsafe { Pin::get_mut_unchecked(Pin::as_mut(&mut self)) };
            let ptr = mut_ref as *mut F as *mut ();
            mem::forget(self); // Don't drop the box
            ptr
        }

        unsafe fn poll(ptr: *mut (), lw: &LocalWaker) -> Poll<T> {
            let ptr = ptr as *mut F;
            let pin: Pin<&mut F> = Pin::new_unchecked(&mut *ptr);
            F::poll(pin, lw)
        }

        unsafe fn drop(ptr: *mut ()) {
            #[allow(clippy::cast_ptr_alignment)]
            drop(Pin::from(Box::from_raw(ptr as *mut F)));
        }
    }

    impl<'a, F: Future<Output = ()> + Send + 'a> From<Pin<Box<F>>> for FutureObj<'a, ()> {
        fn from(boxed: Pin<Box<F>>) -> Self {
            FutureObj::new(boxed)
        }
    }

    impl<'a, F: Future<Output = ()> + Send + 'a> From<Box<F>> for FutureObj<'a, ()> {
        fn from(boxed: Box<F>) -> Self {
            FutureObj::new(boxed)
        }
    }

    impl<'a, F: Future<Output = ()> + 'a> From<Pin<Box<F>>> for LocalFutureObj<'a, ()> {
        fn from(boxed: Pin<Box<F>>) -> Self {
            LocalFutureObj::new(boxed)
        }
    }

    impl<'a, F: Future<Output = ()> + 'a> From<Box<F>> for LocalFutureObj<'a, ()> {
        fn from(boxed: Box<F>) -> Self {
            LocalFutureObj::new(boxed)
        }
    }
}
<|endoftext|>


<commit_before>use ffi::types::herr_t;
use ffi::util::{get_h5_str, string_from_cstr};
use ffi::h5e::{H5Ewalk2, H5Eget_msg, H5E_error2_t, H5Eset_auto2, H5Eget_current_stack,
               H5Eclose_stack, H5E_WALK_DOWNWARD, H5E_DEFAULT};

use std::ptr;
use std::fmt;
use std::ops::Index;
use std::error::Error as BaseError;

use libc::{c_uint, c_void};
use num::{Integer, Zero, Bounded};

pub struct ErrorFrame {
    desc: String,
    func: String,
    major: String,
    minor: String,
}

impl ErrorFrame {
    pub fn new<S1, S2, S3, S4>(desc: S1, func: S2, major: S3, minor: S4) -> ErrorFrame
              where S1: Into<String>, S2: Into<String>, S3: Into<String>, S4: Into<String> {
        ErrorFrame {
            desc: desc.into(),
            func: func.into(),
            major: major.into(),
            minor: minor.into()
        }
    }

    pub fn description(&self) -> &str {
        self.desc.as_ref()
    }

    pub fn detail(&self) -> Option<String> {
        Some(format!("Error in {}(): {} [{}: {}]",
             self.func, self.desc, self.major, self.minor).clone())
    }
}

pub fn silence_errors() {
    h5lock!(H5Eset_auto2(H5E_DEFAULT, None, ptr::null_mut()));
}

pub struct ErrorStack {
    frames: Vec<ErrorFrame>
}

impl Index<usize> for ErrorStack {
    type Output = ErrorFrame;

    fn index<'a>(&'a self, index: usize) -> &'a ErrorFrame {
        &self.frames[index]
    }
}

impl ErrorStack {
    // This low-level function is not thread-safe and has to be synchronized by the user
    pub fn query() -> Result<Option<ErrorStack>> {
        struct CallbackData {
            stack: ErrorStack,
            err: Option<Error>,
        }

        extern fn callback(_: c_uint, err_desc: *const H5E_error2_t, data: *mut c_void) -> herr_t {
            unsafe {
                let data = &mut *(data as *mut CallbackData);
                if data.err.is_some() {
                    return 0;
                }
                let closure = |e: H5E_error2_t| -> Result<ErrorFrame> {
                    let (desc, func) = (string_from_cstr(e.desc), string_from_cstr(e.func_name));
                    let major = try!(get_h5_str(|m, s| {
                        H5Eget_msg(e.maj_num, ptr::null_mut(), m, s)
                    }));
                    let minor = try!(get_h5_str(|m, s| {
                        H5Eget_msg(e.min_num, ptr::null_mut(), m, s)
                    }));
                    Ok(ErrorFrame::new(desc, func, major, minor))
                };
                match closure(*err_desc) {
                    Ok(frame) => { data.stack.push(frame); 0 },
                    Err(err)  => { data.err = Some(From::from(err)); 0 }
                }
            }
        }

        let mut data = CallbackData { stack: ErrorStack::new(), err: None };
        let data_ptr: *mut c_void = &mut data as *mut _ as *mut c_void;

        // known HDF5 bug: H5Eget_msg() may corrupt the current stack, so we copy it first
        unsafe {
            let stack_id = H5Eget_current_stack();
            ensure!(stack_id >= 0, "failed to copy the current error stack");
            H5Ewalk2(stack_id, H5E_WALK_DOWNWARD, Some(callback), data_ptr);
            H5Eclose_stack(stack_id)
        };

        match (data.err, data.stack.is_empty()) {
            (Some(err), _) => Err(err),
            (None, false)  => Ok(Some(data.stack)),
            (None, true)   => Ok(None),
        }
    }

    pub fn new() -> ErrorStack {
        ErrorStack { frames: Vec::new() }
    }

    pub fn len(&self) -> usize {
        self.frames.len()
    }

    pub fn push(&mut self, frame: ErrorFrame) {
        self.frames.push(frame)
    }

    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    pub fn top(&self) -> Option<&ErrorFrame> {
        match !self.is_empty() {
            false => None,
            true  => Some(&self.frames[0]),
        }
    }

    pub fn description(&self) -> &str {
        match self.top() {
            None        => "unknown library error",
            Some(frame) => frame.description(),
        }
    }

    pub fn detail(&self) -> Option<String> {
        match self.top() {
            None        => None,
            Some(frame) => frame.detail(),
        }
    }
}

pub enum Error {
    LibraryError(ErrorStack),
    InternalError(String),
}

pub type Result<T> = ::std::result::Result<T, Error>;

impl Error {
    pub fn query() -> Option<Error> {
        match ErrorStack::query() {
            Err(err)        => Some(From::from(err)),
            Ok(Some(stack)) => Some(Error::LibraryError(stack)),
            Ok(None)        => None,
        }
    }

    pub fn description(&self) -> &str {
        match *self {
            Error::InternalError(ref desc) => desc.as_ref(),
            Error::LibraryError(ref stack) => stack.description(),
        }
    }
}

impl<S> From<S> for Error where S: Into<String> {
    fn from(desc: S) -> Error {
        Error::InternalError(desc.into())
    }
}

impl fmt::Debug for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
        match *self {
            Error::InternalError(ref desc) => desc.fmt(formatter),
            Error::LibraryError(ref stack) => stack.detail().fmt(formatter),
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
        self.description().fmt(formatter)
    }
}

impl ::std::error::Error for Error {
    fn description(&self) -> &str {
        self.description()
    }
}

pub fn h5check<T>(value: T) -> Result<T> where T: Integer + Zero + Bounded,
{
    let min_value: T = Bounded::min_value();
    let zero:      T = Zero::zero();

    let maybe_error = if min_value < zero {
        value < zero
    } else {
        value == zero
    };

    match maybe_error {
        false => Ok(value),
        true  => match Error::query() {
            None       => Ok(value),
            Some(err)  => Err(From::from(err)),
        },
    }
}

#[cfg(test)]
mod tests {
    use ffi::types::herr_t;
    use ffi::h5p::{H5Pcreate, H5Pclose, H5P_ROOT};
    use super::{ErrorStack, Result, silence_errors};

    #[test]
    pub fn test_error_stack() {
        silence_errors();

        let result_no_error = h5lock!({
            let plist_id = H5Pcreate(*H5P_ROOT);
            H5Pclose(plist_id);
            ErrorStack::query()
        });
        assert!(result_no_error.ok().unwrap().is_none());

        let result_error = h5lock!({
            let plist_id = H5Pcreate(*H5P_ROOT);
            H5Pclose(plist_id);
            H5Pclose(plist_id);
            ErrorStack::query()
        });
        let stack = result_error.ok().unwrap().unwrap();
        assert_eq!(stack.description(), "can't close");
        assert_eq!(&stack.detail().unwrap(),
                   "Error in H5Pclose(): can't close [Property lists: Unable to free object]");

        assert_eq!(stack.len(), 3);
        assert!(!stack.is_empty());

        assert_eq!(stack[0].description(), "can't close");
        assert_eq!(&stack[0].detail().unwrap(),
                   "Error in H5Pclose(): can't close \
                    [Property lists: Unable to free object]");

        assert_eq!(stack[1].description(), "can't decrement ID ref count");
        assert_eq!(&stack[1].detail().unwrap(),
                   "Error in H5I_dec_app_ref(): can't decrement ID ref count \
                    [Object atom: Unable to decrement reference count]");

        assert_eq!(stack[2].description(), "can't locate ID");
        assert_eq!(&stack[2].detail().unwrap(),
                   "Error in H5I_dec_ref(): can't locate ID \
                    [Object atom: Unable to find atom information (already closed?)]");

        let empty_stack = ErrorStack::new();
        assert!(empty_stack.is_empty());
        assert_eq!(empty_stack.len(), 0);
    }

    #[test]
    pub fn test_h5call() {
        silence_errors();

        let result_no_error = h5call!({
            let plist_id = H5Pcreate(*H5P_ROOT);
            H5Pclose(plist_id)
        });
        assert!(result_no_error.is_ok());

        let result_error = h5call!({
            let plist_id = H5Pcreate(*H5P_ROOT);
            H5Pclose(plist_id);
            H5Pclose(plist_id)
        });
        assert!(result_error.is_err());
    }

    #[test]
    pub fn test_h5try() {
        silence_errors();

        fn f1() -> Result<herr_t> {
            let plist_id = h5try!(H5Pcreate(*H5P_ROOT));
            h5try!(H5Pclose(plist_id));
            Ok(100)
        }

        let result1 = f1();
        assert!(result1.is_ok());
        assert_eq!(result1.ok().unwrap(), 100);

        fn f2() -> Result<herr_t> {
            let plist_id = h5try!(H5Pcreate(*H5P_ROOT));
            h5try!(H5Pclose(plist_id));
            h5try!(H5Pclose(plist_id));
            Ok(100)
        }

        let result2 = f2();
        assert!(result2.is_err());
    }
}
<commit_msg>Include explicit HDF5 function name in error::Error::description()<commit_after>use ffi::types::herr_t;
use ffi::util::{get_h5_str, string_from_cstr};
use ffi::h5e::{H5Ewalk2, H5Eget_msg, H5E_error2_t, H5Eset_auto2, H5Eget_current_stack,
               H5Eclose_stack, H5E_WALK_DOWNWARD, H5E_DEFAULT};

use std::ptr;
use std::fmt;
use std::ops::Index;
use std::error::Error as BaseError;

use libc::{c_uint, c_void};
use num::{Integer, Zero, Bounded};

pub struct ErrorFrame {
    desc: String,
    func: String,
    major: String,
    minor: String,
    description: String,
}

impl ErrorFrame {
    pub fn new<S1, S2, S3, S4>(desc: S1, func: S2, major: S3, minor: S4) -> ErrorFrame
              where S1: Into<String>, S2: Into<String>, S3: Into<String>, S4: Into<String> {
        let (s_func, s_desc) = (func.into(), desc.into());
        let description = format!("{}(): {}", s_func.clone(), s_desc.clone());
        ErrorFrame {
            desc: s_desc,
            func: s_func,
            major: major.into(),
            minor: minor.into(),
            description: description,
        }
    }

    pub fn description(&self) -> &str {
        self.description.as_ref()
    }

    pub fn detail(&self) -> Option<String> {
        Some(format!("Error in {}(): {} [{}: {}]",
             self.func, self.desc, self.major, self.minor).clone())
    }
}

pub fn silence_errors() {
    h5lock!(H5Eset_auto2(H5E_DEFAULT, None, ptr::null_mut()));
}

pub struct ErrorStack {
    frames: Vec<ErrorFrame>
}

impl Index<usize> for ErrorStack {
    type Output = ErrorFrame;

    fn index<'a>(&'a self, index: usize) -> &'a ErrorFrame {
        &self.frames[index]
    }
}

impl ErrorStack {
    // This low-level function is not thread-safe and has to be synchronized by the user
    pub fn query() -> Result<Option<ErrorStack>> {
        struct CallbackData {
            stack: ErrorStack,
            err: Option<Error>,
        }

        extern fn callback(_: c_uint, err_desc: *const H5E_error2_t, data: *mut c_void) -> herr_t {
            unsafe {
                let data = &mut *(data as *mut CallbackData);
                if data.err.is_some() {
                    return 0;
                }
                let closure = |e: H5E_error2_t| -> Result<ErrorFrame> {
                    let (desc, func) = (string_from_cstr(e.desc), string_from_cstr(e.func_name));
                    let major = try!(get_h5_str(|m, s| {
                        H5Eget_msg(e.maj_num, ptr::null_mut(), m, s)
                    }));
                    let minor = try!(get_h5_str(|m, s| {
                        H5Eget_msg(e.min_num, ptr::null_mut(), m, s)
                    }));
                    Ok(ErrorFrame::new(desc, func, major, minor))
                };
                match closure(*err_desc) {
                    Ok(frame) => { data.stack.push(frame); 0 },
                    Err(err)  => { data.err = Some(From::from(err)); 0 }
                }
            }
        }

        let mut data = CallbackData { stack: ErrorStack::new(), err: None };
        let data_ptr: *mut c_void = &mut data as *mut _ as *mut c_void;

        // known HDF5 bug: H5Eget_msg() may corrupt the current stack, so we copy it first
        unsafe {
            let stack_id = H5Eget_current_stack();
            ensure!(stack_id >= 0, "failed to copy the current error stack");
            H5Ewalk2(stack_id, H5E_WALK_DOWNWARD, Some(callback), data_ptr);
            H5Eclose_stack(stack_id)
        };

        match (data.err, data.stack.is_empty()) {
            (Some(err), _) => Err(err),
            (None, false)  => Ok(Some(data.stack)),
            (None, true)   => Ok(None),
        }
    }

    pub fn new() -> ErrorStack {
        ErrorStack { frames: Vec::new() }
    }

    pub fn len(&self) -> usize {
        self.frames.len()
    }

    pub fn push(&mut self, frame: ErrorFrame) {
        self.frames.push(frame)
    }

    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    pub fn top(&self) -> Option<&ErrorFrame> {
        match !self.is_empty() {
            false => None,
            true  => Some(&self.frames[0]),
        }
    }

    pub fn description(&self) -> &str {
        match self.top() {
            None        => "unknown library error",
            Some(frame) => frame.description(),
        }
    }

    pub fn detail(&self) -> Option<String> {
        match self.top() {
            None        => None,
            Some(frame) => frame.detail(),
        }
    }
}

pub enum Error {
    LibraryError(ErrorStack),
    InternalError(String),
}

pub type Result<T> = ::std::result::Result<T, Error>;

impl Error {
    pub fn query() -> Option<Error> {
        match ErrorStack::query() {
            Err(err)        => Some(From::from(err)),
            Ok(Some(stack)) => Some(Error::LibraryError(stack)),
            Ok(None)        => None,
        }
    }

    pub fn description(&self) -> &str {
        match *self {
            Error::InternalError(ref desc) => desc.as_ref(),
            Error::LibraryError(ref stack) => stack.description(),
        }
    }
}

impl<S> From<S> for Error where S: Into<String> {
    fn from(desc: S) -> Error {
        Error::InternalError(desc.into())
    }
}

impl fmt::Debug for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
        match *self {
            Error::InternalError(ref desc) => desc.fmt(formatter),
            Error::LibraryError(ref stack) => stack.detail().fmt(formatter),
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
        self.description().fmt(formatter)
    }
}

impl ::std::error::Error for Error {
    fn description(&self) -> &str {
        self.description()
    }
}

pub fn h5check<T>(value: T) -> Result<T> where T: Integer + Zero + Bounded,
{
    let min_value: T = Bounded::min_value();
    let zero:      T = Zero::zero();

    let maybe_error = if min_value < zero {
        value < zero
    } else {
        value == zero
    };

    match maybe_error {
        false => Ok(value),
        true  => match Error::query() {
            None       => Ok(value),
            Some(err)  => Err(From::from(err)),
        },
    }
}

#[cfg(test)]
mod tests {
    use ffi::types::herr_t;
    use ffi::h5p::{H5Pcreate, H5Pclose, H5P_ROOT};
    use super::{ErrorStack, Result, silence_errors};

    #[test]
    pub fn test_error_stack() {
        silence_errors();

        let result_no_error = h5lock!({
            let plist_id = H5Pcreate(*H5P_ROOT);
            H5Pclose(plist_id);
            ErrorStack::query()
        });
        assert!(result_no_error.ok().unwrap().is_none());

        let result_error = h5lock!({
            let plist_id = H5Pcreate(*H5P_ROOT);
            H5Pclose(plist_id);
            H5Pclose(plist_id);
            ErrorStack::query()
        });
        let stack = result_error.ok().unwrap().unwrap();
        assert_eq!(stack.description(), "H5Pclose(): can't close");
        assert_eq!(&stack.detail().unwrap(),
                   "Error in H5Pclose(): can't close [Property lists: Unable to free object]");

        assert_eq!(stack.len(), 3);
        assert!(!stack.is_empty());

        assert_eq!(stack[0].description(), "H5Pclose(): can't close");
        assert_eq!(&stack[0].detail().unwrap(),
                   "Error in H5Pclose(): can't close \
                    [Property lists: Unable to free object]");

        assert_eq!(stack[1].description(), "H5I_dec_app_ref(): can't decrement ID ref count");
        assert_eq!(&stack[1].detail().unwrap(),
                   "Error in H5I_dec_app_ref(): can't decrement ID ref count \
                    [Object atom: Unable to decrement reference count]");

        assert_eq!(stack[2].description(), "H5I_dec_ref(): can't locate ID");
        assert_eq!(&stack[2].detail().unwrap(),
                   "Error in H5I_dec_ref(): can't locate ID \
                    [Object atom: Unable to find atom information (already closed?)]");

        let empty_stack = ErrorStack::new();
        assert!(empty_stack.is_empty());
        assert_eq!(empty_stack.len(), 0);
    }

    #[test]
    pub fn test_h5call() {
        silence_errors();

        let result_no_error = h5call!({
            let plist_id = H5Pcreate(*H5P_ROOT);
            H5Pclose(plist_id)
        });
        assert!(result_no_error.is_ok());

        let result_error = h5call!({
            let plist_id = H5Pcreate(*H5P_ROOT);
            H5Pclose(plist_id);
            H5Pclose(plist_id)
        });
        assert!(result_error.is_err());
    }

    #[test]
    pub fn test_h5try() {
        silence_errors();

        fn f1() -> Result<herr_t> {
            let plist_id = h5try!(H5Pcreate(*H5P_ROOT));
            h5try!(H5Pclose(plist_id));
            Ok(100)
        }

        let result1 = f1();
        assert!(result1.is_ok());
        assert_eq!(result1.ok().unwrap(), 100);

        fn f2() -> Result<herr_t> {
            let plist_id = h5try!(H5Pcreate(*H5P_ROOT));
            h5try!(H5Pclose(plist_id));
            h5try!(H5Pclose(plist_id));
            Ok(100)
        }

        let result2 = f2();
        assert!(result2.is_err());
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 Syn Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.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.

use std;
use std::fmt::{self, Display};
use std::iter::FromIterator;

use proc_macro2::{
    Delimiter, Group, Ident, LexError, Literal, Punct, Spacing, Span, TokenStream, TokenTree,
};
#[cfg(feature = "printing")]
use quote::ToTokens;

use buffer::Cursor;
use thread::ThreadBound;

/// The result of a Syn parser.
pub type Result<T> = std::result::Result<T, Error>;

/// Error returned when a Syn parser cannot parse the input tokens.
///
/// Refer to the [module documentation] for details about parsing in Syn.
///
/// [module documentation]: index.html
///
/// *This type is available if Syn is built with the `"parsing"` feature.*
#[derive(Debug)]
pub struct Error {
    // Span is implemented as an index into a thread-local interner to keep the
    // size small. It is not safe to access from a different thread. We want
    // errors to be Send and Sync to play nicely with the Failure crate, so pin
    // the span we're given to its original thread and assume it is
    // Span::call_site if accessed from any other thread.
    start_span: ThreadBound<Span>,
    end_span: ThreadBound<Span>,
    message: String,
}

#[cfg(test)]
struct _Test where Error: Send + Sync;

impl Error {
    /// Usually the [`ParseStream::error`] method will be used instead, which
    /// automatically uses the correct span from the current position of the
    /// parse stream.
    ///
    /// Use `Error::new` when the error needs to be triggered on some span other
    /// than where the parse stream is currently positioned.
    ///
    /// [`ParseStream::error`]: struct.ParseBuffer.html#method.error
    ///
    /// # Example
    ///
    /// ```
    /// #[macro_use]
    /// extern crate syn;
    ///
    /// use syn::{Ident, LitStr};
    /// use syn::parse::{Error, ParseStream, Result};
    ///
    /// // Parses input that looks like `name = "string"` where the key must be
    /// // the identifier `name` and the value may be any string literal.
    /// // Returns the string literal.
    /// fn parse_name(input: ParseStream) -> Result<LitStr> {
    ///     let name_token: Ident = input.parse()?;
    ///     if name_token != "name" {
    ///         // Trigger an error not on the current position of the stream,
    ///         // but on the position of the unexpected identifier.
    ///         return Err(Error::new(name_token.span(), "expected `name`"));
    ///     }
    ///     input.parse::<Token![=]>()?;
    ///     let s: LitStr = input.parse()?;
    ///     Ok(s)
    /// }
    /// #
    /// # fn main() {}
    /// ```
    pub fn new<T: Display>(span: Span, message: T) -> Self {
        Error {
            start_span: ThreadBound::new(span),
            end_span: ThreadBound::new(span),
            message: message.to_string(),
        }
    }

    /// Creates an error which spans the items provided with the specified
    /// message.
    ///
    /// Unlike the `new` constructor this constructors takes a spanned item (the
    /// first argument here). This allows the `Error` returned to attempt to
    /// ensure it spans all the tokens inside of `tokens`. While you typically
    /// can use the `Spanned` trait with the above `new` constructor
    /// implementation limitations today mean that this constructor may provide
    /// a higher-quality error message on stable Rust.
    ///
    /// When in doubt it's recommended to stick to `Error::new` (or
    /// `ParseStream::error`)!
    #[cfg(feature = "printing")]
    pub fn new_spanned<T: ToTokens, U: Display>(tokens: T, message: U) -> Self {
        let mut iter = tokens.into_token_stream().into_iter();
        let start = iter.next().map_or_else(Span::call_site, |t| t.span());
        let end = iter.last().map_or(start, |t| t.span());
        Error {
            start_span: ThreadBound::new(start),
            end_span: ThreadBound::new(end),
            message: message.to_string(),
        }
    }

    /// The source location of the error.
    ///
    /// Spans are not thread-safe so this function returns `Span::call_site()`
    /// if called from a different thread than the one on which the `Error` was
    /// originally created.
    pub fn span(&self) -> Span {
        let start = match self.start_span.get() {
            Some(span) => *span,
            None => return Span::call_site(),
        };

        #[cfg(procmacro2_semver_exempt)]
        {
            let end = match self.end_span.get() {
                Some(span) => *span,
                None => return Span::call_site(),
            };
            start.join(end).unwrap_or(start)
        }
        #[cfg(not(procmacro2_semver_exempt))]
        {
            start
        }
    }

    /// Render the error as an invocation of [`compile_error!`].
    ///
    /// The [`parse_macro_input!`] macro provides a convenient way to invoke
    /// this method correctly in a procedural macro.
    ///
    /// [`compile_error!`]: https://doc.rust-lang.org/std/macro.compile_error.html
    /// [`parse_macro_input!`]: ../macro.parse_macro_input.html
    pub fn to_compile_error(&self) -> TokenStream {
        let start = self.start_span.get().cloned().unwrap_or_else(Span::call_site);
        let end = self.end_span.get().cloned().unwrap_or_else(Span::call_site);

        // compile_error!($message)
        TokenStream::from_iter(vec![
            TokenTree::Ident(Ident::new("compile_error", start)),
            TokenTree::Punct({
                let mut punct = Punct::new('!', Spacing::Alone);
                punct.set_span(start);
                punct
            }),
            TokenTree::Group({
                let mut group = Group::new(Delimiter::Brace, {
                    TokenStream::from_iter(vec![TokenTree::Literal({
                        let mut string = Literal::string(&self.message);
                        string.set_span(end);
                        string
                    })])
                });
                group.set_span(end);
                group
            }),
        ])
    }
}

pub fn new_at<T: Display>(scope: Span, cursor: Cursor, message: T) -> Error {
    if cursor.eof() {
        Error::new(scope, format!("unexpected end of input, {}", message))
    } else {
        Error::new(cursor.span(), message)
    }
}

impl Display for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str(&self.message)
    }
}

impl Clone for Error {
    fn clone(&self) -> Self {
        let start = self.start_span.get().cloned().unwrap_or_else(Span::call_site);
        let end = self.end_span.get().cloned().unwrap_or_else(Span::call_site);
        Error {
            start_span: ThreadBound::new(start),
            end_span: ThreadBound::new(end),
            message: self.message.clone(),
        }
    }
}

impl std::error::Error for Error {
    fn description(&self) -> &str {
        "parse error"
    }
}

impl From<LexError> for Error {
    fn from(err: LexError) -> Self {
        Error::new(Span::call_site(), format!("{:?}", err))
    }
}
<commit_msg>Clarify wording of Error::new_spanned documentation<commit_after>// Copyright 2018 Syn Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.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.

use std;
use std::fmt::{self, Display};
use std::iter::FromIterator;

use proc_macro2::{
    Delimiter, Group, Ident, LexError, Literal, Punct, Spacing, Span, TokenStream, TokenTree,
};
#[cfg(feature = "printing")]
use quote::ToTokens;

use buffer::Cursor;
use thread::ThreadBound;

/// The result of a Syn parser.
pub type Result<T> = std::result::Result<T, Error>;

/// Error returned when a Syn parser cannot parse the input tokens.
///
/// Refer to the [module documentation] for details about parsing in Syn.
///
/// [module documentation]: index.html
///
/// *This type is available if Syn is built with the `"parsing"` feature.*
#[derive(Debug)]
pub struct Error {
    // Span is implemented as an index into a thread-local interner to keep the
    // size small. It is not safe to access from a different thread. We want
    // errors to be Send and Sync to play nicely with the Failure crate, so pin
    // the span we're given to its original thread and assume it is
    // Span::call_site if accessed from any other thread.
    start_span: ThreadBound<Span>,
    end_span: ThreadBound<Span>,
    message: String,
}

#[cfg(test)]
struct _Test where Error: Send + Sync;

impl Error {
    /// Usually the [`ParseStream::error`] method will be used instead, which
    /// automatically uses the correct span from the current position of the
    /// parse stream.
    ///
    /// Use `Error::new` when the error needs to be triggered on some span other
    /// than where the parse stream is currently positioned.
    ///
    /// [`ParseStream::error`]: struct.ParseBuffer.html#method.error
    ///
    /// # Example
    ///
    /// ```
    /// #[macro_use]
    /// extern crate syn;
    ///
    /// use syn::{Ident, LitStr};
    /// use syn::parse::{Error, ParseStream, Result};
    ///
    /// // Parses input that looks like `name = "string"` where the key must be
    /// // the identifier `name` and the value may be any string literal.
    /// // Returns the string literal.
    /// fn parse_name(input: ParseStream) -> Result<LitStr> {
    ///     let name_token: Ident = input.parse()?;
    ///     if name_token != "name" {
    ///         // Trigger an error not on the current position of the stream,
    ///         // but on the position of the unexpected identifier.
    ///         return Err(Error::new(name_token.span(), "expected `name`"));
    ///     }
    ///     input.parse::<Token![=]>()?;
    ///     let s: LitStr = input.parse()?;
    ///     Ok(s)
    /// }
    /// #
    /// # fn main() {}
    /// ```
    pub fn new<T: Display>(span: Span, message: T) -> Self {
        Error {
            start_span: ThreadBound::new(span),
            end_span: ThreadBound::new(span),
            message: message.to_string(),
        }
    }

    /// Creates an error with the specified message spanning the given syntax
    /// tree node.
    ///
    /// Unlike the `Error::new` constructor, this constructor takes an argument
    /// `tokens` which is a syntax tree node. This allows the resulting `Error`
    /// to attempt to span all tokens inside of `tokens`. While you would
    /// typically be able to use the `Spanned` trait with the above `Error::new`
    /// constructor, implementation limitations today mean that
    /// `Error::new_spanned` may provide a higher-quality error message on
    /// stable Rust.
    ///
    /// When in doubt it's recommended to stick to `Error::new` (or
    /// `ParseStream::error`)!
    #[cfg(feature = "printing")]
    pub fn new_spanned<T: ToTokens, U: Display>(tokens: T, message: U) -> Self {
        let mut iter = tokens.into_token_stream().into_iter();
        let start = iter.next().map_or_else(Span::call_site, |t| t.span());
        let end = iter.last().map_or(start, |t| t.span());
        Error {
            start_span: ThreadBound::new(start),
            end_span: ThreadBound::new(end),
            message: message.to_string(),
        }
    }

    /// The source location of the error.
    ///
    /// Spans are not thread-safe so this function returns `Span::call_site()`
    /// if called from a different thread than the one on which the `Error` was
    /// originally created.
    pub fn span(&self) -> Span {
        let start = match self.start_span.get() {
            Some(span) => *span,
            None => return Span::call_site(),
        };

        #[cfg(procmacro2_semver_exempt)]
        {
            let end = match self.end_span.get() {
                Some(span) => *span,
                None => return Span::call_site(),
            };
            start.join(end).unwrap_or(start)
        }
        #[cfg(not(procmacro2_semver_exempt))]
        {
            start
        }
    }

    /// Render the error as an invocation of [`compile_error!`].
    ///
    /// The [`parse_macro_input!`] macro provides a convenient way to invoke
    /// this method correctly in a procedural macro.
    ///
    /// [`compile_error!`]: https://doc.rust-lang.org/std/macro.compile_error.html
    /// [`parse_macro_input!`]: ../macro.parse_macro_input.html
    pub fn to_compile_error(&self) -> TokenStream {
        let start = self.start_span.get().cloned().unwrap_or_else(Span::call_site);
        let end = self.end_span.get().cloned().unwrap_or_else(Span::call_site);

        // compile_error!($message)
        TokenStream::from_iter(vec![
            TokenTree::Ident(Ident::new("compile_error", start)),
            TokenTree::Punct({
                let mut punct = Punct::new('!', Spacing::Alone);
                punct.set_span(start);
                punct
            }),
            TokenTree::Group({
                let mut group = Group::new(Delimiter::Brace, {
                    TokenStream::from_iter(vec![TokenTree::Literal({
                        let mut string = Literal::string(&self.message);
                        string.set_span(end);
                        string
                    })])
                });
                group.set_span(end);
                group
            }),
        ])
    }
}

pub fn new_at<T: Display>(scope: Span, cursor: Cursor, message: T) -> Error {
    if cursor.eof() {
        Error::new(scope, format!("unexpected end of input, {}", message))
    } else {
        Error::new(cursor.span(), message)
    }
}

impl Display for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str(&self.message)
    }
}

impl Clone for Error {
    fn clone(&self) -> Self {
        let start = self.start_span.get().cloned().unwrap_or_else(Span::call_site);
        let end = self.end_span.get().cloned().unwrap_or_else(Span::call_site);
        Error {
            start_span: ThreadBound::new(start),
            end_span: ThreadBound::new(end),
            message: self.message.clone(),
        }
    }
}

impl std::error::Error for Error {
    fn description(&self) -> &str {
        "parse error"
    }
}

impl From<LexError> for Error {
    fn from(err: LexError) -> Self {
        Error::new(Span::call_site(), format!("{:?}", err))
    }
}
<|endoftext|>


<commit_before>//! Processor state stored in the FLAGS, EFLAGS, or RFLAGS register.

use PrivilegeLevel;

/// The RFLAGS register. All variants are backwards compatable so only one
/// bitflags struct needed.
bitflags! {
    pub flags Flags: usize {
        /// ID Flag (ID)
        const FLAGS_ID = 1 << 21,
        /// Virtual Interrupt Pending (VIP)
        const FLAGS_VIP = 1 << 20,
        /// Virtual Interrupt Flag (VIF)
        const FLAGS_VIF = 1 << 19,
        /// Alignment Check (AC)
        const FLAGS_AC = 1 << 18,
        /// Virtual-8086 Mode (VM)
        const FLAGS_VM = 1 << 17,
        /// Resume Flag (RF)
        const FLAGS_RF = 1 << 16,
        /// Nested Task (NT)
        const FLAGS_NT = 1 << 14,
        /// I/O Privilege Level (IOPL) 0
        const FLAGS_IOPL0 = 0 << 12,
        /// I/O Privilege Level (IOPL) 1
        const FLAGS_IOPL1 = 1 << 12,
        /// I/O Privilege Level (IOPL) 2
        const FLAGS_IOPL2 = 2 << 12,
        /// I/O Privilege Level (IOPL) 3
        const FLAGS_IOPL3 = 3 << 12,
        /// Overflow Flag (OF)
        const FLAGS_OF = 1 << 11,
        /// Direction Flag (DF)
        const FLAGS_DF = 1 << 10,
        /// Interrupt Enable Flag (IF)
        const FLAGS_IF = 1 << 9,
        /// Trap Flag (TF)
        const FLAGS_TF = 1 << 8,
        /// Sign Flag (SF)
        const FLAGS_SF = 1 << 7,
        /// Zero Flag (ZF)
        const FLAGS_ZF = 1 << 6,
        /// Auxiliary Carry Flag (AF)
        const FLAGS_AF = 1 << 4,
        /// Parity Flag (PF)
        const FLAGS_PF = 1 << 2,
        /// Bit 1 is always 1.
        const FLAGS_A1 = 1 << 1,
        /// Carry Flag (CF)
        const FLAGS_CF = 1 << 0,
    }
}

impl Flags {
    /// Creates a new Flags entry. Ensures bit 1 is set.
    pub const fn new() -> Flags {
        FLAGS_A1
    }

    /// Creates a new Flags with the given I/O privilege level.
    pub const fn from_priv(iopl: PrivilegeLevel) -> Flags {
        Flags { bits: (iopl as usize) << 12 }
    }
}

pub fn flags() -> Flags {

    #[cfg(target_arch="x86")]
    #[inline(always)]
    unsafe fn inner() -> Flags {
        let r: usize;
        asm!("pushfl; popl $0" : "=r"(r) :: "memory");
        Flags::from_bits_truncate(r)
    }

    #[cfg(target_arch="x86_64")]
    #[inline(always)]
    unsafe fn inner() -> Flags {
        let r: usize;
        asm!("pushfq; popq $0" : "=r"(r) :: "memory");
        Flags::from_bits_truncate(r)
    }

    unsafe { inner() }
}

pub fn set(val: Flags) {

    #[cfg(target_arch="x86")]
    #[inline(always)]
    unsafe fn inner(val: Flags) {
        asm!("pushl $0; popfl" :: "r"(val.bits()) : "memory" "flags");
    }

    #[cfg(target_arch="x86_64")]
    #[inline(always)]
    unsafe fn inner(val: Flags) {
        asm!("pushq $0; popfq" :: "r"(val.bits()) : "memory" "flags");
    }

    unsafe { inner(val) }
}
<commit_msg>Remove 32-bit compatibility<commit_after>//! Processor state stored in the FLAGS, EFLAGS, or RFLAGS register.

/// The RFLAGS register. All variants are backwards compatable so only one
/// bitflags struct needed.
bitflags! {
    pub flags Flags: usize {
        /// ID Flag (ID)
        const ID = 1 << 21,
        /// Virtual Interrupt Pending (VIP)
        const VIP = 1 << 20,
        /// Virtual Interrupt Flag (VIF)
        const VIF = 1 << 19,
        /// Alignment Check (AC)
        const AC = 1 << 18,
        /// Virtual-8086 Mode (VM)
        const VM = 1 << 17,
        /// Resume Flag (RF)
        const RF = 1 << 16,
        /// Nested Task (NT)
        const NT = 1 << 14,
        /// I/O Privilege Level (IOPL) 0
        const IOPL0 = 0 << 12,
        /// I/O Privilege Level (IOPL) 1
        const IOPL1 = 1 << 12,
        /// I/O Privilege Level (IOPL) 2
        const IOPL2 = 2 << 12,
        /// I/O Privilege Level (IOPL) 3
        const IOPL3 = 3 << 12,
        /// Overflow Flag (OF)
        const OF = 1 << 11,
        /// Direction Flag (DF)
        const DF = 1 << 10,
        /// Interrupt Enable Flag (IF)
        const IF = 1 << 9,
        /// Trap Flag (TF)
        const TF = 1 << 8,
        /// Sign Flag (SF)
        const SF = 1 << 7,
        /// Zero Flag (ZF)
        const ZF = 1 << 6,
        /// Auxiliary Carry Flag (AF)
        const AF = 1 << 4,
        /// Parity Flag (PF)
        const PF = 1 << 2,
        /// Bit 1 is always 1.
        const A1 = 1 << 1,
        /// Carry Flag (CF)
        const CF = 1 << 0,
    }
}

pub fn flags() -> Flags {
    let r: usize;
    unsafe { asm!("pushfq; popq $0" : "=r"(r) :: "memory") };
    Flags::from_bits_truncate(r)
}

pub fn set_flags(val: Flags) {
    unsafe { asm!("pushq $0; popfq" :: "r"(val.bits()) : "memory" "flags") };
}
<|endoftext|>