<commit_before>// Copyright 2012-2013 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 middle::def::*;
use middle::ty;
use middle::typeck;
use util::ppaux;

use syntax::ast::*;
use syntax::ast_util;
use syntax::visit::Visitor;
use syntax::visit;

struct CheckCrateVisitor<'a, 'tcx: 'a> {
    tcx: &'a ty::ctxt<'tcx>,
    in_const: bool
}

impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
    fn with_const(&mut self, in_const: bool, f: |&mut CheckCrateVisitor<'a, 'tcx>|) {
        let was_const = self.in_const;
        self.in_const = in_const;
        f(self);
        self.in_const = was_const;
    }
    fn inside_const(&mut self, f: |&mut CheckCrateVisitor<'a, 'tcx>|) {
        self.with_const(true, f);
    }
    fn outside_const(&mut self, f: |&mut CheckCrateVisitor<'a, 'tcx>|) {
        self.with_const(false, f);
    }
}

impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
    fn visit_item(&mut self, i: &Item) {
        check_item(self, i);
    }
    fn visit_pat(&mut self, p: &Pat) {
        check_pat(self, p);
    }
    fn visit_expr(&mut self, ex: &Expr) {
        check_expr(self, ex);
    }
}

pub fn check_crate(tcx: &ty::ctxt) {
    visit::walk_crate(&mut CheckCrateVisitor { tcx: tcx, in_const: false },
                      tcx.map.krate());
    tcx.sess.abort_if_errors();
}

fn check_item(v: &mut CheckCrateVisitor, it: &Item) {
    match it.node {
        ItemStatic(_, _, ref ex) => {
            v.inside_const(|v| v.visit_expr(&**ex));
        }
        ItemEnum(ref enum_definition, _) => {
            for var in (*enum_definition).variants.iter() {
                for ex in var.node.disr_expr.iter() {
                    v.inside_const(|v| v.visit_expr(&**ex));
                }
            }
        }
        _ => v.outside_const(|v| visit::walk_item(v, it))
    }
}

fn check_pat(v: &mut CheckCrateVisitor, p: &Pat) {
    fn is_str(e: &Expr) -> bool {
        match e.node {
            ExprBox(_, ref expr) => {
                match expr.node {
                    ExprLit(ref lit) => ast_util::lit_is_str(&**lit),
                    _ => false,
                }
            }
            _ => false,
        }
    }
    match p.node {
        // Let through plain ~-string literals here
        PatLit(ref a) => if !is_str(&**a) { v.inside_const(|v| v.visit_expr(&**a)); },
        PatRange(ref a, ref b) => {
            if !is_str(&**a) { v.inside_const(|v| v.visit_expr(&**a)); }
            if !is_str(&**b) { v.inside_const(|v| v.visit_expr(&**b)); }
        }
        _ => v.outside_const(|v| visit::walk_pat(v, p))
    }
}

fn check_expr(v: &mut CheckCrateVisitor, e: &Expr) {
    if v.in_const {
        match e.node {
          ExprUnary(UnDeref, _) => { }
          ExprUnary(UnUniq, _) => {
            span_err!(v.tcx.sess, e.span, E0010, "cannot do allocations in constant expressions");
            return;
          }
          ExprLit(ref lit) if ast_util::lit_is_str(&**lit) => {}
          ExprBinary(..) | ExprUnary(..) => {
            let method_call = typeck::MethodCall::expr(e.id);
            if v.tcx.method_map.borrow().contains_key(&method_call) {
                span_err!(v.tcx.sess, e.span, E0011,
                    "user-defined operators are not allowed in constant expressions");
            }
          }
          ExprLit(_) => (),
          ExprCast(_, _) => {
            let ety = ty::expr_ty(v.tcx, e);
            if !ty::type_is_numeric(ety) && !ty::type_is_unsafe_ptr(ety) {
                span_err!(v.tcx.sess, e.span, E0012,
                    "can not cast to `{}` in a constant expression",
                    ppaux::ty_to_string(v.tcx, ety)
                );
            }
          }
          ExprPath(ref pth) => {
            // NB: In the future you might wish to relax this slightly
            // to handle on-demand instantiation of functions via
            // foo::<bar> in a const. Currently that is only done on
            // a path in trans::callee that only works in block contexts.
            if !pth.segments.iter().all(|segment| segment.types.is_empty()) {
                span_err!(v.tcx.sess, e.span, E0013,
                    "paths in constants may only refer to items without type parameters");
            }
            match v.tcx.def_map.borrow().find(&e.id) {
              Some(&DefStatic(..)) |
              Some(&DefFn(..)) |
              Some(&DefVariant(_, _, _)) |
              Some(&DefStruct(_)) => { }

              Some(&def) => {
                debug!("(checking const) found bad def: {:?}", def);
                span_err!(v.tcx.sess, e.span, E0014,
                    "paths in constants may only refer to constants or functions");
              }
              None => {
                v.tcx.sess.span_bug(e.span, "unbound path in const?!");
              }
            }
          }
          ExprCall(ref callee, _) => {
            match v.tcx.def_map.borrow().find(&callee.id) {
                Some(&DefStruct(..)) |
                Some(&DefVariant(..)) => {}    // OK.
                _ => {
                    span_err!(v.tcx.sess, e.span, E0015,
                      "function calls in constants are limited to struct and enum constructors");
                }
            }
          }
          ExprBlock(ref block) => {
            // Check all statements in the block
            for stmt in block.stmts.iter() {
                let block_span_err = |span|
                    span_err!(v.tcx.sess, span, E0016,
                        "blocks in constants are limited to items and tail expressions");
                match stmt.node {
                    StmtDecl(ref span, _) => {
                        match span.node {
                            DeclLocal(_) => block_span_err(span.span),

                            // Item statements are allowed
                            DeclItem(_) => {}
                        }
                    }
                    StmtExpr(ref expr, _) => block_span_err(expr.span),
                    StmtSemi(ref semi, _) => block_span_err(semi.span),
                    StmtMac(..) => v.tcx.sess.span_bug(e.span,
                        "unexpanded statement macro in const?!")
                }
            }
            match block.expr {
                Some(ref expr) => check_expr(v, &**expr),
                None => {}
            }
          }
          ExprVec(_) |
          ExprAddrOf(MutImmutable, _) |
          ExprParen(..) |
          ExprField(..) |
          ExprTupField(..) |
          ExprIndex(..) |
          ExprTup(..) |
          ExprRepeat(..) |
          ExprStruct(..) => { }
          ExprAddrOf(_, ref inner) => {
                match inner.node {
                    // Mutable slices are allowed.
                    ExprVec(_) => {}
                    _ => span_err!(v.tcx.sess, e.span, E0017,
                                   "references in constants may only refer to immutable values")

                }
          },

          _ => {
              span_err!(v.tcx.sess, e.span, E0019,
                  "constant contains unimplemented expression type");
              return;
          }
        }
    }
    visit::walk_expr(v, e);
}
<commit_msg>rustc: Reformat check_const with modern style<commit_after>// Copyright 2012-2013 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 middle::def::*;
use middle::ty;
use middle::typeck;
use util::ppaux;

use syntax::ast::*;
use syntax::ast_util;
use syntax::visit::Visitor;
use syntax::visit;

struct CheckCrateVisitor<'a, 'tcx: 'a> {
    tcx: &'a ty::ctxt<'tcx>,
    in_const: bool
}

impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
    fn with_const(&mut self, in_const: bool, f: |&mut CheckCrateVisitor<'a, 'tcx>|) {
        let was_const = self.in_const;
        self.in_const = in_const;
        f(self);
        self.in_const = was_const;
    }
    fn inside_const(&mut self, f: |&mut CheckCrateVisitor<'a, 'tcx>|) {
        self.with_const(true, f);
    }
    fn outside_const(&mut self, f: |&mut CheckCrateVisitor<'a, 'tcx>|) {
        self.with_const(false, f);
    }
}

impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
    fn visit_item(&mut self, i: &Item) {
        check_item(self, i);
    }
    fn visit_pat(&mut self, p: &Pat) {
        check_pat(self, p);
    }
    fn visit_expr(&mut self, ex: &Expr) {
        if check_expr(self, ex) {
            visit::walk_expr(v, e);
        }
    }
}

pub fn check_crate(tcx: &ty::ctxt) {
    visit::walk_crate(&mut CheckCrateVisitor { tcx: tcx, in_const: false },
                      tcx.map.krate());
    tcx.sess.abort_if_errors();
}

fn check_item(v: &mut CheckCrateVisitor, it: &Item) {
    match it.node {
        ItemStatic(_, _, ref ex) => {
            v.inside_const(|v| v.visit_expr(&**ex));
        }
        ItemEnum(ref enum_definition, _) => {
            for var in (*enum_definition).variants.iter() {
                for ex in var.node.disr_expr.iter() {
                    v.inside_const(|v| v.visit_expr(&**ex));
                }
            }
        }
        _ => v.outside_const(|v| visit::walk_item(v, it))
    }
}

fn check_pat(v: &mut CheckCrateVisitor, p: &Pat) {
    fn is_str(e: &Expr) -> bool {
        match e.node {
            ExprBox(_, ref expr) => {
                match expr.node {
                    ExprLit(ref lit) => ast_util::lit_is_str(&**lit),
                    _ => false,
                }
            }
            _ => false,
        }
    }
    match p.node {
        // Let through plain ~-string literals here
        PatLit(ref a) => if !is_str(&**a) { v.inside_const(|v| v.visit_expr(&**a)); },
        PatRange(ref a, ref b) => {
            if !is_str(&**a) { v.inside_const(|v| v.visit_expr(&**a)); }
            if !is_str(&**b) { v.inside_const(|v| v.visit_expr(&**b)); }
        }
        _ => v.outside_const(|v| visit::walk_pat(v, p))
    }
}

fn check_expr(v: &mut CheckCrateVisitor, e: &Expr) -> bool {
    if !v.in_const { return true }

    match e.node {
        ExprUnary(UnDeref, _) => {}
        ExprUnary(UnUniq, _) => {
            span_err!(v.tcx.sess, e.span, E0010,
                      "cannot do allocations in constant expressions");
            return false;
        }
        ExprLit(ref lit) if ast_util::lit_is_str(&**lit) => {}
        ExprBinary(..) | ExprUnary(..) => {
            let method_call = typeck::MethodCall::expr(e.id);
            if v.tcx.method_map.borrow().contains_key(&method_call) {
                span_err!(v.tcx.sess, e.span, E0011,
                          "user-defined operators are not allowed in constant \
                           expressions");
            }
        }
        ExprLit(_) => (),
        ExprCast(_, _) => {
            let ety = ty::expr_ty(v.tcx, e);
            if !ty::type_is_numeric(ety) && !ty::type_is_unsafe_ptr(ety) {
                span_err!(v.tcx.sess, e.span, E0012,
                          "can not cast to `{}` in a constant expression",
                          ppaux::ty_to_string(v.tcx, ety));
            }
        }
        ExprPath(ref pth) => {
            // NB: In the future you might wish to relax this slightly
            // to handle on-demand instantiation of functions via
            // foo::<bar> in a const. Currently that is only done on
            // a path in trans::callee that only works in block contexts.
            if !pth.segments.iter().all(|segment| segment.types.is_empty()) {
                span_err!(v.tcx.sess, e.span, E0013,
                          "paths in constants may only refer to items without \
                           type parameters");
            }
            match v.tcx.def_map.borrow().find(&e.id) {
                Some(&DefStatic(..)) |
                Some(&DefFn(..)) |
                Some(&DefVariant(_, _, _)) |
                Some(&DefStruct(_)) => { }

                Some(&def) => {
                    debug!("(checking const) found bad def: {:?}", def);
                    span_err!(v.tcx.sess, e.span, E0014,
                              "paths in constants may only refer to constants \
                               or functions");
                }
                None => {
                    v.tcx.sess.span_bug(e.span, "unbound path in const?!");
                }
            }
        }
        ExprCall(ref callee, _) => {
            match v.tcx.def_map.borrow().find(&callee.id) {
                Some(&DefStruct(..)) |
                Some(&DefVariant(..)) => {}    // OK.

                _ => {
                    span_err!(v.tcx.sess, e.span, E0015,
                              "function calls in constants are limited to \
                               struct and enum constructors");
                }
            }
        }
        ExprBlock(ref block) => {
            // Check all statements in the block
            for stmt in block.stmts.iter() {
                let block_span_err = |span|
                    span_err!(v.tcx.sess, span, E0016,
                              "blocks in constants are limited to items and \
                               tail expressions");
                match stmt.node {
                    StmtDecl(ref span, _) => {
                        match span.node {
                            DeclLocal(_) => block_span_err(span.span),

                            // Item statements are allowed
                            DeclItem(_) => {}
                        }
                    }
                    StmtExpr(ref expr, _) => block_span_err(expr.span),
                    StmtSemi(ref semi, _) => block_span_err(semi.span),
                    StmtMac(..) => {
                        v.tcx.sess.span_bug(e.span, "unexpanded statement \
                                                     macro in const?!")
                    }
                }
            }
            match block.expr {
                Some(ref expr) => check_expr(v, &**expr),
                None => {}
            }
        }
        ExprVec(_) |
        ExprAddrOf(MutImmutable, _) |
        ExprParen(..) |
        ExprField(..) |
        ExprTupField(..) |
        ExprIndex(..) |
        ExprTup(..) |
        ExprRepeat(..) |
        ExprStruct(..) => {}

        ExprAddrOf(_, ref inner) => {
            match inner.node {
                // Mutable slices are allowed.
                ExprVec(_) => {}
                _ => span_err!(v.tcx.sess, e.span, E0017,
                               "references in constants may only refer \
                                to immutable values")

            }
        }

        _ => {
            span_err!(v.tcx.sess, e.span, E0019,
                      "constant contains unimplemented expression type");
            return false;
        }
    }
    true
}
<|endoftext|>


<commit_before>// Copyright 2013 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.

/*!

Dynamic library facilities.

A simple wrapper over the platform's dynamic library facilities

*/

use c_str::ToCStr;
use iter::Iterator;
use mem;
use ops::*;
use option::*;
use os;
use path::GenericPath;
use path;
use result::*;
use slice::{Vector,OwnedVector};
use str;
use vec::Vec;

pub struct DynamicLibrary { handle: *u8}

impl Drop for DynamicLibrary {
    fn drop(&mut self) {
        match dl::check_for_errors_in(|| {
            unsafe {
                dl::close(self.handle)
            }
        }) {
            Ok(()) => {},
            Err(str) => fail!("{}", str)
        }
    }
}

impl DynamicLibrary {
    /// Lazily open a dynamic library. When passed None it gives a
    /// handle to the calling process
    pub fn open(filename: Option<&path::Path>) -> Result<DynamicLibrary, ~str> {
        unsafe {
            let maybe_library = dl::check_for_errors_in(|| {
                match filename {
                    Some(name) => dl::open_external(name),
                    None => dl::open_internal()
                }
            });

            // The dynamic library must not be constructed if there is
            // an error opening the library so the destructor does not
            // run.
            match maybe_library {
                Err(err) => Err(err),
                Ok(handle) => Ok(DynamicLibrary { handle: handle })
            }
        }
    }

    /// Appends a path to the system search path for dynamic libraries
    pub fn add_search_path(path: &path::Path) {
        let (envvar, sep) = if cfg!(windows) {
            ("PATH", ';' as u8)
        } else if cfg!(target_os = "macos") {
            ("DYLD_LIBRARY_PATH", ':' as u8)
        } else {
            ("LD_LIBRARY_PATH", ':' as u8)
        };
        let newenv = os::getenv_as_bytes(envvar).unwrap_or(box []);
        let mut newenv = newenv.move_iter().collect::<Vec<_>>();
        newenv.push_all(&[sep]);
        newenv.push_all(path.as_vec());
        os::setenv(envvar, str::from_utf8(newenv.as_slice()).unwrap());
    }

    /// Access the value at the symbol of the dynamic library
    pub unsafe fn symbol<T>(&self, symbol: &str) -> Result<T, ~str> {
        // This function should have a lifetime constraint of 'a on
        // T but that feature is still unimplemented

        let maybe_symbol_value = dl::check_for_errors_in(|| {
            symbol.with_c_str(|raw_string| {
                dl::symbol(self.handle, raw_string)
            })
        });

        // The value must not be constructed if there is an error so
        // the destructor does not run.
        match maybe_symbol_value {
            Err(err) => Err(err),
            Ok(symbol_value) => Ok(mem::transmute(symbol_value))
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use prelude::*;
    use libc;

    #[test]
    #[ignore(cfg(windows))] // FIXME #8818
    #[ignore(cfg(target_os="android"))] // FIXME(#10379)
    fn test_loading_cosine() {
        // The math library does not need to be loaded since it is already
        // statically linked in
        let libm = match DynamicLibrary::open(None) {
            Err(error) => fail!("Could not load self as module: {}", error),
            Ok(libm) => libm
        };

        let cosine: extern fn(libc::c_double) -> libc::c_double = unsafe {
            match libm.symbol("cos") {
                Err(error) => fail!("Could not load function cos: {}", error),
                Ok(cosine) => cosine
            }
        };

        let argument = 0.0;
        let expected_result = 1.0;
        let result = cosine(argument);
        if result != expected_result {
            fail!("cos({:?}) != {:?} but equaled {:?} instead", argument,
                   expected_result, result)
        }
    }

    #[test]
    #[cfg(target_os = "linux")]
    #[cfg(target_os = "macos")]
    #[cfg(target_os = "freebsd")]
    fn test_errors_do_not_crash() {
        // Open /dev/null as a library to get an error, and make sure
        // that only causes an error, and not a crash.
        let path = GenericPath::new("/dev/null");
        match DynamicLibrary::open(Some(&path)) {
            Err(_) => {}
            Ok(_) => fail!("Successfully opened the empty library.")
        }
    }
}

#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
#[cfg(target_os = "macos")]
#[cfg(target_os = "freebsd")]
pub mod dl {
    use c_str::ToCStr;
    use libc;
    use path;
    use ptr;
    use str;
    use result::*;

    pub unsafe fn open_external(filename: &path::Path) -> *u8 {
        filename.with_c_str(|raw_name| {
            dlopen(raw_name, Lazy as libc::c_int) as *u8
        })
    }

    pub unsafe fn open_internal() -> *u8 {
        dlopen(ptr::null(), Lazy as libc::c_int) as *u8
    }

    pub fn check_for_errors_in<T>(f: || -> T) -> Result<T, ~str> {
        use unstable::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
        static mut lock: StaticNativeMutex = NATIVE_MUTEX_INIT;
        unsafe {
            // dlerror isn't thread safe, so we need to lock around this entire
            // sequence
            let _guard = lock.lock();
            let _old_error = dlerror();

            let result = f();

            let last_error = dlerror();
            let ret = if ptr::null() == last_error {
                Ok(result)
            } else {
                Err(str::raw::from_c_str(last_error))
            };

            ret
        }
    }

    pub unsafe fn symbol(handle: *u8, symbol: *libc::c_char) -> *u8 {
        dlsym(handle as *libc::c_void, symbol) as *u8
    }
    pub unsafe fn close(handle: *u8) {
        dlclose(handle as *libc::c_void); ()
    }

    pub enum RTLD {
        Lazy = 1,
        Now = 2,
        Global = 256,
        Local = 0,
    }

    #[link_name = "dl"]
    extern {
        fn dlopen(filename: *libc::c_char, flag: libc::c_int) -> *libc::c_void;
        fn dlerror() -> *libc::c_char;
        fn dlsym(handle: *libc::c_void, symbol: *libc::c_char) -> *libc::c_void;
        fn dlclose(handle: *libc::c_void) -> libc::c_int;
    }
}

#[cfg(target_os = "win32")]
pub mod dl {
    use libc;
    use os;
    use ptr;
    use result::{Ok, Err, Result};

    pub unsafe fn open_external(filename: &path::Path) -> *u8 {
        os::win32::as_utf16_p(filename.as_str().unwrap(), |raw_name| {
            LoadLibraryW(raw_name as *libc::c_void) as *u8
        })
    }

    pub unsafe fn open_internal() -> *u8 {
        let handle = ptr::null();
        GetModuleHandleExW(0 as libc::DWORD, ptr::null(), &handle as **libc::c_void);
        handle as *u8
    }

    pub fn check_for_errors_in<T>(f: || -> T) -> Result<T, ~str> {
        unsafe {
            SetLastError(0);

            let result = f();

            let error = os::errno();
            if 0 == error {
                Ok(result)
            } else {
                Err(format!("Error code {}", error))
            }
        }
    }

    pub unsafe fn symbol(handle: *u8, symbol: *libc::c_char) -> *u8 {
        GetProcAddress(handle as *libc::c_void, symbol) as *u8
    }
    pub unsafe fn close(handle: *u8) {
        FreeLibrary(handle as *libc::c_void); ()
    }

    extern "system" {
        fn SetLastError(error: libc::size_t);
        fn LoadLibraryW(name: *libc::c_void) -> *libc::c_void;
        fn GetModuleHandleExW(dwFlags: libc::DWORD, name: *u16,
                              handle: **libc::c_void) -> *libc::c_void;
        fn GetProcAddress(handle: *libc::c_void, name: *libc::c_char) -> *libc::c_void;
        fn FreeLibrary(handle: *libc::c_void);
    }
}
<commit_msg>Change dynamic_library::open_external to take ToCStr<commit_after>// Copyright 2013 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.

/*!

Dynamic library facilities.

A simple wrapper over the platform's dynamic library facilities

*/

use c_str::ToCStr;
use iter::Iterator;
use mem;
use ops::*;
use option::*;
use os;
use path::GenericPath;
use path;
use result::*;
use slice::{Vector,OwnedVector};
use str;
use vec::Vec;

pub struct DynamicLibrary { handle: *u8}

impl Drop for DynamicLibrary {
    fn drop(&mut self) {
        match dl::check_for_errors_in(|| {
            unsafe {
                dl::close(self.handle)
            }
        }) {
            Ok(()) => {},
            Err(str) => fail!("{}", str)
        }
    }
}

impl DynamicLibrary {
    // FIXME (#12938): Until DST lands, we cannot decompose &str into
    // & and str, so we cannot usefully take ToCStr arguments by
    // reference (without forcing an additional & around &str). So we
    // are instead temporarily adding an instance for &Path, so that
    // we can take ToCStr as owned. When DST lands, the &Path instance
    // should be removed, and arguments bound by ToCStr should be
    // passed by reference. (Here: in the `open` method.)

    /// Lazily open a dynamic library. When passed None it gives a
    /// handle to the calling process
    pub fn open<T: ToCStr>(filename: Option<T>)
                        -> Result<DynamicLibrary, ~str> {
        unsafe {
            let mut filename = filename;
            let maybe_library = dl::check_for_errors_in(|| {
                match filename.take() {
                    Some(name) => dl::open_external(name),
                    None => dl::open_internal()
                }
            });

            // The dynamic library must not be constructed if there is
            // an error opening the library so the destructor does not
            // run.
            match maybe_library {
                Err(err) => Err(err),
                Ok(handle) => Ok(DynamicLibrary { handle: handle })
            }
        }
    }

    /// Appends a path to the system search path for dynamic libraries
    pub fn add_search_path(path: &path::Path) {
        let (envvar, sep) = if cfg!(windows) {
            ("PATH", ';' as u8)
        } else if cfg!(target_os = "macos") {
            ("DYLD_LIBRARY_PATH", ':' as u8)
        } else {
            ("LD_LIBRARY_PATH", ':' as u8)
        };
        let newenv = os::getenv_as_bytes(envvar).unwrap_or(box []);
        let mut newenv = newenv.move_iter().collect::<Vec<_>>();
        newenv.push_all(&[sep]);
        newenv.push_all(path.as_vec());
        os::setenv(envvar, str::from_utf8(newenv.as_slice()).unwrap());
    }

    /// Access the value at the symbol of the dynamic library
    pub unsafe fn symbol<T>(&self, symbol: &str) -> Result<T, ~str> {
        // This function should have a lifetime constraint of 'a on
        // T but that feature is still unimplemented

        let maybe_symbol_value = dl::check_for_errors_in(|| {
            symbol.with_c_str(|raw_string| {
                dl::symbol(self.handle, raw_string)
            })
        });

        // The value must not be constructed if there is an error so
        // the destructor does not run.
        match maybe_symbol_value {
            Err(err) => Err(err),
            Ok(symbol_value) => Ok(mem::transmute(symbol_value))
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use prelude::*;
    use libc;

    #[test]
    #[ignore(cfg(windows))] // FIXME #8818
    #[ignore(cfg(target_os="android"))] // FIXME(#10379)
    fn test_loading_cosine() {
        // The math library does not need to be loaded since it is already
        // statically linked in
        let none: Option<Path> = None; // appease the typechecker
        let libm = match DynamicLibrary::open(none) {
            Err(error) => fail!("Could not load self as module: {}", error),
            Ok(libm) => libm
        };

        let cosine: extern fn(libc::c_double) -> libc::c_double = unsafe {
            match libm.symbol("cos") {
                Err(error) => fail!("Could not load function cos: {}", error),
                Ok(cosine) => cosine
            }
        };

        let argument = 0.0;
        let expected_result = 1.0;
        let result = cosine(argument);
        if result != expected_result {
            fail!("cos({:?}) != {:?} but equaled {:?} instead", argument,
                   expected_result, result)
        }
    }

    #[test]
    #[cfg(target_os = "linux")]
    #[cfg(target_os = "macos")]
    #[cfg(target_os = "freebsd")]
    fn test_errors_do_not_crash() {
        // Open /dev/null as a library to get an error, and make sure
        // that only causes an error, and not a crash.
        let path = Path::new("/dev/null");
        match DynamicLibrary::open(Some(&path)) {
            Err(_) => {}
            Ok(_) => fail!("Successfully opened the empty library.")
        }
    }
}

#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
#[cfg(target_os = "macos")]
#[cfg(target_os = "freebsd")]
pub mod dl {
    use c_str::ToCStr;
    use libc;
    use ptr;
    use str;
    use result::*;

    pub unsafe fn open_external<T: ToCStr>(filename: T) -> *u8 {
        filename.with_c_str(|raw_name| {
            dlopen(raw_name, Lazy as libc::c_int) as *u8
        })
    }

    pub unsafe fn open_internal() -> *u8 {
        dlopen(ptr::null(), Lazy as libc::c_int) as *u8
    }

    pub fn check_for_errors_in<T>(f: || -> T) -> Result<T, ~str> {
        use unstable::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
        static mut lock: StaticNativeMutex = NATIVE_MUTEX_INIT;
        unsafe {
            // dlerror isn't thread safe, so we need to lock around this entire
            // sequence
            let _guard = lock.lock();
            let _old_error = dlerror();

            let result = f();

            let last_error = dlerror();
            let ret = if ptr::null() == last_error {
                Ok(result)
            } else {
                Err(str::raw::from_c_str(last_error))
            };

            ret
        }
    }

    pub unsafe fn symbol(handle: *u8, symbol: *libc::c_char) -> *u8 {
        dlsym(handle as *libc::c_void, symbol) as *u8
    }
    pub unsafe fn close(handle: *u8) {
        dlclose(handle as *libc::c_void); ()
    }

    pub enum RTLD {
        Lazy = 1,
        Now = 2,
        Global = 256,
        Local = 0,
    }

    #[link_name = "dl"]
    extern {
        fn dlopen(filename: *libc::c_char, flag: libc::c_int) -> *libc::c_void;
        fn dlerror() -> *libc::c_char;
        fn dlsym(handle: *libc::c_void, symbol: *libc::c_char) -> *libc::c_void;
        fn dlclose(handle: *libc::c_void) -> libc::c_int;
    }
}

#[cfg(target_os = "win32")]
pub mod dl {
    use libc;
    use os;
    use ptr;
    use result::{Ok, Err, Result};
    use str;
    use c_str::ToCStr;

    pub unsafe fn open_external<T: ToCStr>(filename: T) -> *u8 {
        // Windows expects Unicode data
        let filename_cstr = filename.to_c_str();
        let filename_str = str::from_utf8(filename_cstr.as_bytes_no_nul()).unwrap();
        os::win32::as_utf16_p(filename_str, |raw_name| {
            LoadLibraryW(raw_name as *libc::c_void) as *u8
        })
    }

    pub unsafe fn open_internal() -> *u8 {
        let handle = ptr::null();
        GetModuleHandleExW(0 as libc::DWORD, ptr::null(), &handle as **libc::c_void);
        handle as *u8
    }

    pub fn check_for_errors_in<T>(f: || -> T) -> Result<T, ~str> {
        unsafe {
            SetLastError(0);

            let result = f();

            let error = os::errno();
            if 0 == error {
                Ok(result)
            } else {
                Err(format!("Error code {}", error))
            }
        }
    }

    pub unsafe fn symbol(handle: *u8, symbol: *libc::c_char) -> *u8 {
        GetProcAddress(handle as *libc::c_void, symbol) as *u8
    }
    pub unsafe fn close(handle: *u8) {
        FreeLibrary(handle as *libc::c_void); ()
    }

    extern "system" {
        fn SetLastError(error: libc::size_t);
        fn LoadLibraryW(name: *libc::c_void) -> *libc::c_void;
        fn GetModuleHandleExW(dwFlags: libc::DWORD, name: *u16,
                              handle: **libc::c_void) -> *libc::c_void;
        fn GetProcAddress(handle: *libc::c_void, name: *libc::c_char) -> *libc::c_void;
        fn FreeLibrary(handle: *libc::c_void);
    }
}
<|endoftext|>


<commit_before>// Copyright 2012 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.

// Detecting language items.
//
// Language items are items that represent concepts intrinsic to the language
// itself. Examples are:
//
// * Traits that specify "kinds"; e.g. "Sync", "Send".
//
// * Traits that represent operators; e.g. "Add", "Sub", "Index".
//
// * Functions called by the compiler itself.

pub use self::LangItem::*;

use dep_graph::DepNode;
use front::map as hir_map;
use session::Session;
use middle::cstore::CrateStore;
use middle::def_id::DefId;
use middle::ty;
use middle::weak_lang_items;
use util::nodemap::FnvHashMap;

use syntax::ast;
use syntax::attr::AttrMetaMethods;
use syntax::codemap::Span;
use syntax::parse::token::InternedString;
use rustc_front::intravisit::Visitor;
use rustc_front::hir;

// The actual lang items defined come at the end of this file in one handy table.
// So you probably just want to nip down to the end.
macro_rules! lets_do_this {
    (
        $( $variant:ident, $name:expr, $method:ident; )*
    ) => {

enum_from_u32! {
    #[derive(Copy, Clone, PartialEq, Eq, Hash)]
    pub enum LangItem {
        $($variant,)*
    }
}

pub struct LanguageItems {
    pub items: Vec<Option<DefId>>,
    pub missing: Vec<LangItem>,
}

impl LanguageItems {
    pub fn new() -> LanguageItems {
        fn foo(_: LangItem) -> Option<DefId> { None }

        LanguageItems {
            items: vec!($(foo($variant)),*),
            missing: Vec::new(),
        }
    }

    pub fn items(&self) -> &[Option<DefId>] {
        &*self.items
    }

    pub fn item_name(index: usize) -> &'static str {
        let item: Option<LangItem> = LangItem::from_u32(index as u32);
        match item {
            $( Some($variant) => $name, )*
            None => "???"
        }
    }

    pub fn require(&self, it: LangItem) -> Result<DefId, String> {
        match self.items[it as usize] {
            Some(id) => Ok(id),
            None => {
                Err(format!("requires `{}` lang_item",
                            LanguageItems::item_name(it as usize)))
            }
        }
    }

    pub fn require_owned_box(&self) -> Result<DefId, String> {
        self.require(OwnedBoxLangItem)
    }

    pub fn from_builtin_kind(&self, bound: ty::BuiltinBound)
                             -> Result<DefId, String>
    {
        match bound {
            ty::BoundSend => self.require(SendTraitLangItem),
            ty::BoundSized => self.require(SizedTraitLangItem),
            ty::BoundCopy => self.require(CopyTraitLangItem),
            ty::BoundSync => self.require(SyncTraitLangItem),
        }
    }

    pub fn to_builtin_kind(&self, id: DefId) -> Option<ty::BuiltinBound> {
        if Some(id) == self.send_trait() {
            Some(ty::BoundSend)
        } else if Some(id) == self.sized_trait() {
            Some(ty::BoundSized)
        } else if Some(id) == self.copy_trait() {
            Some(ty::BoundCopy)
        } else if Some(id) == self.sync_trait() {
            Some(ty::BoundSync)
        } else {
            None
        }
    }

    pub fn fn_trait_kind(&self, id: DefId) -> Option<ty::ClosureKind> {
        let def_id_kinds = [
            (self.fn_trait(), ty::FnClosureKind),
            (self.fn_mut_trait(), ty::FnMutClosureKind),
            (self.fn_once_trait(), ty::FnOnceClosureKind),
            ];

        for &(opt_def_id, kind) in &def_id_kinds {
            if Some(id) == opt_def_id {
                return Some(kind);
            }
        }

        None
    }

    $(
        #[allow(dead_code)]
        pub fn $method(&self) -> Option<DefId> {
            self.items[$variant as usize]
        }
    )*
}

struct LanguageItemCollector<'a, 'tcx: 'a> {
    items: LanguageItems,

    ast_map: &'a hir_map::Map<'tcx>,

    session: &'a Session,

    item_refs: FnvHashMap<&'static str, usize>,
}

impl<'a, 'v, 'tcx> Visitor<'v> for LanguageItemCollector<'a, 'tcx> {
    fn visit_item(&mut self, item: &hir::Item) {
        if let Some(value) = extract(&item.attrs) {
            let item_index = self.item_refs.get(&value[..]).cloned();

            if let Some(item_index) = item_index {
                self.collect_item(item_index, self.ast_map.local_def_id(item.id), item.span)
            }
        }
    }
}

impl<'a, 'tcx> LanguageItemCollector<'a, 'tcx> {
    pub fn new(session: &'a Session, ast_map: &'a hir_map::Map<'tcx>)
               -> LanguageItemCollector<'a, 'tcx> {
        let mut item_refs = FnvHashMap();

        $( item_refs.insert($name, $variant as usize); )*

        LanguageItemCollector {
            session: session,
            ast_map: ast_map,
            items: LanguageItems::new(),
            item_refs: item_refs,
        }
    }

    pub fn collect_item(&mut self, item_index: usize,
                        item_def_id: DefId, span: Span) {
        // Check for duplicates.
        match self.items.items[item_index] {
            Some(original_def_id) if original_def_id != item_def_id => {
                let cstore = &self.session.cstore;
                let span = self.ast_map.span_if_local(original_def_id).unwrap_or(span);
                let mut err = struct_span_err!(self.session,
                                                span,
                                                E0152,
                                                "Duplicate lang item found: `{}`.",
                                                LanguageItems::item_name(item_index));
                if let Some(span) = self.ast_map.span_if_local(item_def_id) {
                    span_note!(&mut err, span,
                               "First defined here.");
                } else {
                    span_note!(&mut err, span,
                               "First defined in crate `{}`.",
                               cstore.crate_name(item_def_id.krate));
                }
                err.emit();
            }
            _ => {
                // OK.
            }
        }

        // Matched.
        self.items.items[item_index] = Some(item_def_id);
    }

    pub fn collect_local_language_items(&mut self, krate: &hir::Crate) {
        krate.visit_all_items(self);
    }

    pub fn collect_external_language_items(&mut self, krate: &hir::Crate) {
        let cstore = &self.session.cstore;
        for cnum in cstore.crates() {
            for (index, item_index) in cstore.lang_items(cnum) {
                let def_id = DefId { krate: cnum, index: index };
                self.collect_item(item_index, def_id, krate.span);
            }
        }
    }

    pub fn collect(&mut self, krate: &hir::Crate) {
        self.collect_local_language_items(krate);
        self.collect_external_language_items(krate);
    }
}

pub fn extract(attrs: &[ast::Attribute]) -> Option<InternedString> {
    for attribute in attrs {
        match attribute.value_str() {
            Some(ref value) if attribute.check_name("lang") => {
                return Some(value.clone());
            }
            _ => {}
        }
    }

    return None;
}

pub fn collect_language_items(session: &Session,
                              map: &hir_map::Map)
                              -> LanguageItems {
    let _task = map.dep_graph.in_task(DepNode::CollectLanguageItems);
    let krate: &hir::Crate = map.krate();
    let mut collector = LanguageItemCollector::new(session, map);
    collector.collect(krate);
    let LanguageItemCollector { mut items, .. } = collector;
    weak_lang_items::check_crate(krate, session, &mut items);
    items
}

// End of the macro
    }
}

lets_do_this! {
//  Variant name,                    Name,                      Method name;
    CharImplItem,                    "char",                    char_impl;
    StrImplItem,                     "str",                     str_impl;
    SliceImplItem,                   "slice",                   slice_impl;
    ConstPtrImplItem,                "const_ptr",               const_ptr_impl;
    MutPtrImplItem,                  "mut_ptr",                 mut_ptr_impl;
    I8ImplItem,                      "i8",                      i8_impl;
    I16ImplItem,                     "i16",                     i16_impl;
    I32ImplItem,                     "i32",                     i32_impl;
    I64ImplItem,                     "i64",                     i64_impl;
    IsizeImplItem,                   "isize",                   isize_impl;
    U8ImplItem,                      "u8",                      u8_impl;
    U16ImplItem,                     "u16",                     u16_impl;
    U32ImplItem,                     "u32",                     u32_impl;
    U64ImplItem,                     "u64",                     u64_impl;
    UsizeImplItem,                   "usize",                   usize_impl;
    F32ImplItem,                     "f32",                     f32_impl;
    F64ImplItem,                     "f64",                     f64_impl;

    SendTraitLangItem,               "send",                    send_trait;
    SizedTraitLangItem,              "sized",                   sized_trait;
    UnsizeTraitLangItem,             "unsize",                  unsize_trait;
    CopyTraitLangItem,               "copy",                    copy_trait;
    SyncTraitLangItem,               "sync",                    sync_trait;

    DropTraitLangItem,               "drop",                    drop_trait;

    CoerceUnsizedTraitLangItem,      "coerce_unsized",          coerce_unsized_trait;

    AddTraitLangItem,                "add",                     add_trait;
    SubTraitLangItem,                "sub",                     sub_trait;
    MulTraitLangItem,                "mul",                     mul_trait;
    DivTraitLangItem,                "div",                     div_trait;
    RemTraitLangItem,                "rem",                     rem_trait;
    NegTraitLangItem,                "neg",                     neg_trait;
    NotTraitLangItem,                "not",                     not_trait;
    BitXorTraitLangItem,             "bitxor",                  bitxor_trait;
    BitAndTraitLangItem,             "bitand",                  bitand_trait;
    BitOrTraitLangItem,              "bitor",                   bitor_trait;
    ShlTraitLangItem,                "shl",                     shl_trait;
    ShrTraitLangItem,                "shr",                     shr_trait;
    AddAssignTraitLangItem,          "add_assign",              add_assign_trait;
    SubAssignTraitLangItem,          "sub_assign",              sub_assign_trait;
    MulAssignTraitLangItem,          "mul_assign",              mul_assign_trait;
    DivAssignTraitLangItem,          "div_assign",              div_assign_trait;
    RemAssignTraitLangItem,          "rem_assign",              rem_assign_trait;
    BitXorAssignTraitLangItem,       "bitxor_assign",           bitxor_assign_trait;
    BitAndAssignTraitLangItem,       "bitand_assign",           bitand_assign_trait;
    BitOrAssignTraitLangItem,        "bitor_assign",            bitor_assign_trait;
    ShlAssignTraitLangItem,          "shl_assign",              shl_assign_trait;
    ShrAssignTraitLangItem,          "shr_assign",              shr_assign_trait;
    IndexTraitLangItem,              "index",                   index_trait;
    IndexMutTraitLangItem,           "index_mut",               index_mut_trait;
    RangeStructLangItem,             "range",                   range_struct;
    RangeFromStructLangItem,         "range_from",              range_from_struct;
    RangeToStructLangItem,           "range_to",                range_to_struct;
    RangeFullStructLangItem,         "range_full",              range_full_struct;

    UnsafeCellTypeLangItem,          "unsafe_cell",             unsafe_cell_type;

    DerefTraitLangItem,              "deref",                   deref_trait;
    DerefMutTraitLangItem,           "deref_mut",               deref_mut_trait;

    FnTraitLangItem,                 "fn",                      fn_trait;
    FnMutTraitLangItem,              "fn_mut",                  fn_mut_trait;
    FnOnceTraitLangItem,             "fn_once",                 fn_once_trait;

    EqTraitLangItem,                 "eq",                      eq_trait;
    OrdTraitLangItem,                "ord",                     ord_trait;

    StrEqFnLangItem,                 "str_eq",                  str_eq_fn;

    // A number of panic-related lang items. The `panic` item corresponds to
    // divide-by-zero and various panic cases with `match`. The
    // `panic_bounds_check` item is for indexing arrays.
    //
    // The `begin_unwind` lang item has a predefined symbol name and is sort of
    // a "weak lang item" in the sense that a crate is not required to have it
    // defined to use it, but a final product is required to define it
    // somewhere. Additionally, there are restrictions on crates that use a weak
    // lang item, but do not have it defined.
    PanicFnLangItem,                 "panic",                   panic_fn;
    PanicBoundsCheckFnLangItem,      "panic_bounds_check",      panic_bounds_check_fn;
    PanicFmtLangItem,                "panic_fmt",               panic_fmt;

    ExchangeMallocFnLangItem,        "exchange_malloc",         exchange_malloc_fn;
    ExchangeFreeFnLangItem,          "exchange_free",           exchange_free_fn;
    BoxFreeFnLangItem,               "box_free",                box_free_fn;
    StrDupUniqFnLangItem,            "strdup_uniq",             strdup_uniq_fn;

    StartFnLangItem,                 "start",                   start_fn;

    EhPersonalityLangItem,           "eh_personality",          eh_personality;
    EhPersonalityCatchLangItem,      "eh_personality_catch",    eh_personality_catch;
    EhUnwindResumeLangItem,          "eh_unwind_resume",        eh_unwind_resume;
    MSVCTryFilterLangItem,           "msvc_try_filter",         msvc_try_filter;

    OwnedBoxLangItem,                "owned_box",               owned_box;

    PhantomDataItem,                 "phantom_data",            phantom_data;

    // Deprecated:
    CovariantTypeItem,               "covariant_type",          covariant_type;
    ContravariantTypeItem,           "contravariant_type",      contravariant_type;
    InvariantTypeItem,               "invariant_type",          invariant_type;
    CovariantLifetimeItem,           "covariant_lifetime",      covariant_lifetime;
    ContravariantLifetimeItem,       "contravariant_lifetime",  contravariant_lifetime;
    InvariantLifetimeItem,           "invariant_lifetime",      invariant_lifetime;

    NoCopyItem,                      "no_copy_bound",           no_copy_bound;

    NonZeroItem,                     "non_zero",                non_zero;

    DebugTraitLangItem,              "debug_trait",             debug_trait;
}
<commit_msg>Swap lang item collect order (externals are now collected before locals)<commit_after>// Copyright 2012 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.

// Detecting language items.
//
// Language items are items that represent concepts intrinsic to the language
// itself. Examples are:
//
// * Traits that specify "kinds"; e.g. "Sync", "Send".
//
// * Traits that represent operators; e.g. "Add", "Sub", "Index".
//
// * Functions called by the compiler itself.

pub use self::LangItem::*;

use dep_graph::DepNode;
use front::map as hir_map;
use session::Session;
use middle::cstore::CrateStore;
use middle::def_id::DefId;
use middle::ty;
use middle::weak_lang_items;
use util::nodemap::FnvHashMap;

use syntax::ast;
use syntax::attr::AttrMetaMethods;
use syntax::codemap::Span;
use syntax::parse::token::InternedString;
use rustc_front::intravisit::Visitor;
use rustc_front::hir;

// The actual lang items defined come at the end of this file in one handy table.
// So you probably just want to nip down to the end.
macro_rules! lets_do_this {
    (
        $( $variant:ident, $name:expr, $method:ident; )*
    ) => {

enum_from_u32! {
    #[derive(Copy, Clone, PartialEq, Eq, Hash)]
    pub enum LangItem {
        $($variant,)*
    }
}

pub struct LanguageItems {
    pub items: Vec<Option<DefId>>,
    pub missing: Vec<LangItem>,
}

impl LanguageItems {
    pub fn new() -> LanguageItems {
        fn foo(_: LangItem) -> Option<DefId> { None }

        LanguageItems {
            items: vec!($(foo($variant)),*),
            missing: Vec::new(),
        }
    }

    pub fn items(&self) -> &[Option<DefId>] {
        &*self.items
    }

    pub fn item_name(index: usize) -> &'static str {
        let item: Option<LangItem> = LangItem::from_u32(index as u32);
        match item {
            $( Some($variant) => $name, )*
            None => "???"
        }
    }

    pub fn require(&self, it: LangItem) -> Result<DefId, String> {
        match self.items[it as usize] {
            Some(id) => Ok(id),
            None => {
                Err(format!("requires `{}` lang_item",
                            LanguageItems::item_name(it as usize)))
            }
        }
    }

    pub fn require_owned_box(&self) -> Result<DefId, String> {
        self.require(OwnedBoxLangItem)
    }

    pub fn from_builtin_kind(&self, bound: ty::BuiltinBound)
                             -> Result<DefId, String>
    {
        match bound {
            ty::BoundSend => self.require(SendTraitLangItem),
            ty::BoundSized => self.require(SizedTraitLangItem),
            ty::BoundCopy => self.require(CopyTraitLangItem),
            ty::BoundSync => self.require(SyncTraitLangItem),
        }
    }

    pub fn to_builtin_kind(&self, id: DefId) -> Option<ty::BuiltinBound> {
        if Some(id) == self.send_trait() {
            Some(ty::BoundSend)
        } else if Some(id) == self.sized_trait() {
            Some(ty::BoundSized)
        } else if Some(id) == self.copy_trait() {
            Some(ty::BoundCopy)
        } else if Some(id) == self.sync_trait() {
            Some(ty::BoundSync)
        } else {
            None
        }
    }

    pub fn fn_trait_kind(&self, id: DefId) -> Option<ty::ClosureKind> {
        let def_id_kinds = [
            (self.fn_trait(), ty::FnClosureKind),
            (self.fn_mut_trait(), ty::FnMutClosureKind),
            (self.fn_once_trait(), ty::FnOnceClosureKind),
            ];

        for &(opt_def_id, kind) in &def_id_kinds {
            if Some(id) == opt_def_id {
                return Some(kind);
            }
        }

        None
    }

    $(
        #[allow(dead_code)]
        pub fn $method(&self) -> Option<DefId> {
            self.items[$variant as usize]
        }
    )*
}

struct LanguageItemCollector<'a, 'tcx: 'a> {
    items: LanguageItems,

    ast_map: &'a hir_map::Map<'tcx>,

    session: &'a Session,

    item_refs: FnvHashMap<&'static str, usize>,
}

impl<'a, 'v, 'tcx> Visitor<'v> for LanguageItemCollector<'a, 'tcx> {
    fn visit_item(&mut self, item: &hir::Item) {
        if let Some(value) = extract(&item.attrs) {
            let item_index = self.item_refs.get(&value[..]).cloned();

            if let Some(item_index) = item_index {
                self.collect_item(item_index, self.ast_map.local_def_id(item.id), item.span)
            }
        }
    }
}

impl<'a, 'tcx> LanguageItemCollector<'a, 'tcx> {
    pub fn new(session: &'a Session, ast_map: &'a hir_map::Map<'tcx>)
               -> LanguageItemCollector<'a, 'tcx> {
        let mut item_refs = FnvHashMap();

        $( item_refs.insert($name, $variant as usize); )*

        LanguageItemCollector {
            session: session,
            ast_map: ast_map,
            items: LanguageItems::new(),
            item_refs: item_refs,
        }
    }

    pub fn collect_item(&mut self, item_index: usize,
                        item_def_id: DefId, span: Span) {
        // Check for duplicates.
        match self.items.items[item_index] {
            Some(original_def_id) if original_def_id != item_def_id => {
                let cstore = &self.session.cstore;
                let span = self.ast_map.span_if_local(item_def_id).unwrap_or(span);
                let mut err = struct_span_err!(self.session,
                                                span,
                                                E0152,
                                                "Duplicate lang item found: `{}`.",
                                                LanguageItems::item_name(item_index));
                if let Some(span) = self.ast_map.span_if_local(original_def_id) {
                    span_note!(&mut err, span,
                               "First defined here.");
                } else {
                    span_note!(&mut err, span,
                               "First defined in crate `{}`.",
                               cstore.crate_name(original_def_id.krate));
                }
                err.emit();
            }
            _ => {
                // OK.
            }
        }

        // Matched.
        self.items.items[item_index] = Some(item_def_id);
    }

    pub fn collect_local_language_items(&mut self, krate: &hir::Crate) {
        krate.visit_all_items(self);
    }

    pub fn collect_external_language_items(&mut self, krate: &hir::Crate) {
        let cstore = &self.session.cstore;
        for cnum in cstore.crates() {
            for (index, item_index) in cstore.lang_items(cnum) {
                let def_id = DefId { krate: cnum, index: index };
                self.collect_item(item_index, def_id, krate.span);
            }
        }
    }

    pub fn collect(&mut self, krate: &hir::Crate) {
        self.collect_external_language_items(krate);
        self.collect_local_language_items(krate);
    }
}

pub fn extract(attrs: &[ast::Attribute]) -> Option<InternedString> {
    for attribute in attrs {
        match attribute.value_str() {
            Some(ref value) if attribute.check_name("lang") => {
                return Some(value.clone());
            }
            _ => {}
        }
    }

    return None;
}

pub fn collect_language_items(session: &Session,
                              map: &hir_map::Map)
                              -> LanguageItems {
    let _task = map.dep_graph.in_task(DepNode::CollectLanguageItems);
    let krate: &hir::Crate = map.krate();
    let mut collector = LanguageItemCollector::new(session, map);
    collector.collect(krate);
    let LanguageItemCollector { mut items, .. } = collector;
    weak_lang_items::check_crate(krate, session, &mut items);
    items
}

// End of the macro
    }
}

lets_do_this! {
//  Variant name,                    Name,                      Method name;
    CharImplItem,                    "char",                    char_impl;
    StrImplItem,                     "str",                     str_impl;
    SliceImplItem,                   "slice",                   slice_impl;
    ConstPtrImplItem,                "const_ptr",               const_ptr_impl;
    MutPtrImplItem,                  "mut_ptr",                 mut_ptr_impl;
    I8ImplItem,                      "i8",                      i8_impl;
    I16ImplItem,                     "i16",                     i16_impl;
    I32ImplItem,                     "i32",                     i32_impl;
    I64ImplItem,                     "i64",                     i64_impl;
    IsizeImplItem,                   "isize",                   isize_impl;
    U8ImplItem,                      "u8",                      u8_impl;
    U16ImplItem,                     "u16",                     u16_impl;
    U32ImplItem,                     "u32",                     u32_impl;
    U64ImplItem,                     "u64",                     u64_impl;
    UsizeImplItem,                   "usize",                   usize_impl;
    F32ImplItem,                     "f32",                     f32_impl;
    F64ImplItem,                     "f64",                     f64_impl;

    SendTraitLangItem,               "send",                    send_trait;
    SizedTraitLangItem,              "sized",                   sized_trait;
    UnsizeTraitLangItem,             "unsize",                  unsize_trait;
    CopyTraitLangItem,               "copy",                    copy_trait;
    SyncTraitLangItem,               "sync",                    sync_trait;

    DropTraitLangItem,               "drop",                    drop_trait;

    CoerceUnsizedTraitLangItem,      "coerce_unsized",          coerce_unsized_trait;

    AddTraitLangItem,                "add",                     add_trait;
    SubTraitLangItem,                "sub",                     sub_trait;
    MulTraitLangItem,                "mul",                     mul_trait;
    DivTraitLangItem,                "div",                     div_trait;
    RemTraitLangItem,                "rem",                     rem_trait;
    NegTraitLangItem,                "neg",                     neg_trait;
    NotTraitLangItem,                "not",                     not_trait;
    BitXorTraitLangItem,             "bitxor",                  bitxor_trait;
    BitAndTraitLangItem,             "bitand",                  bitand_trait;
    BitOrTraitLangItem,              "bitor",                   bitor_trait;
    ShlTraitLangItem,                "shl",                     shl_trait;
    ShrTraitLangItem,                "shr",                     shr_trait;
    AddAssignTraitLangItem,          "add_assign",              add_assign_trait;
    SubAssignTraitLangItem,          "sub_assign",              sub_assign_trait;
    MulAssignTraitLangItem,          "mul_assign",              mul_assign_trait;
    DivAssignTraitLangItem,          "div_assign",              div_assign_trait;
    RemAssignTraitLangItem,          "rem_assign",              rem_assign_trait;
    BitXorAssignTraitLangItem,       "bitxor_assign",           bitxor_assign_trait;
    BitAndAssignTraitLangItem,       "bitand_assign",           bitand_assign_trait;
    BitOrAssignTraitLangItem,        "bitor_assign",            bitor_assign_trait;
    ShlAssignTraitLangItem,          "shl_assign",              shl_assign_trait;
    ShrAssignTraitLangItem,          "shr_assign",              shr_assign_trait;
    IndexTraitLangItem,              "index",                   index_trait;
    IndexMutTraitLangItem,           "index_mut",               index_mut_trait;
    RangeStructLangItem,             "range",                   range_struct;
    RangeFromStructLangItem,         "range_from",              range_from_struct;
    RangeToStructLangItem,           "range_to",                range_to_struct;
    RangeFullStructLangItem,         "range_full",              range_full_struct;

    UnsafeCellTypeLangItem,          "unsafe_cell",             unsafe_cell_type;

    DerefTraitLangItem,              "deref",                   deref_trait;
    DerefMutTraitLangItem,           "deref_mut",               deref_mut_trait;

    FnTraitLangItem,                 "fn",                      fn_trait;
    FnMutTraitLangItem,              "fn_mut",                  fn_mut_trait;
    FnOnceTraitLangItem,             "fn_once",                 fn_once_trait;

    EqTraitLangItem,                 "eq",                      eq_trait;
    OrdTraitLangItem,                "ord",                     ord_trait;

    StrEqFnLangItem,                 "str_eq",                  str_eq_fn;

    // A number of panic-related lang items. The `panic` item corresponds to
    // divide-by-zero and various panic cases with `match`. The
    // `panic_bounds_check` item is for indexing arrays.
    //
    // The `begin_unwind` lang item has a predefined symbol name and is sort of
    // a "weak lang item" in the sense that a crate is not required to have it
    // defined to use it, but a final product is required to define it
    // somewhere. Additionally, there are restrictions on crates that use a weak
    // lang item, but do not have it defined.
    PanicFnLangItem,                 "panic",                   panic_fn;
    PanicBoundsCheckFnLangItem,      "panic_bounds_check",      panic_bounds_check_fn;
    PanicFmtLangItem,                "panic_fmt",               panic_fmt;

    ExchangeMallocFnLangItem,        "exchange_malloc",         exchange_malloc_fn;
    ExchangeFreeFnLangItem,          "exchange_free",           exchange_free_fn;
    BoxFreeFnLangItem,               "box_free",                box_free_fn;
    StrDupUniqFnLangItem,            "strdup_uniq",             strdup_uniq_fn;

    StartFnLangItem,                 "start",                   start_fn;

    EhPersonalityLangItem,           "eh_personality",          eh_personality;
    EhPersonalityCatchLangItem,      "eh_personality_catch",    eh_personality_catch;
    EhUnwindResumeLangItem,          "eh_unwind_resume",        eh_unwind_resume;
    MSVCTryFilterLangItem,           "msvc_try_filter",         msvc_try_filter;

    OwnedBoxLangItem,                "owned_box",               owned_box;

    PhantomDataItem,                 "phantom_data",            phantom_data;

    // Deprecated:
    CovariantTypeItem,               "covariant_type",          covariant_type;
    ContravariantTypeItem,           "contravariant_type",      contravariant_type;
    InvariantTypeItem,               "invariant_type",          invariant_type;
    CovariantLifetimeItem,           "covariant_lifetime",      covariant_lifetime;
    ContravariantLifetimeItem,       "contravariant_lifetime",  contravariant_lifetime;
    InvariantLifetimeItem,           "invariant_lifetime",      invariant_lifetime;

    NoCopyItem,                      "no_copy_bound",           no_copy_bound;

    NonZeroItem,                     "non_zero",                non_zero;

    DebugTraitLangItem,              "debug_trait",             debug_trait;
}
<|endoftext|>


<commit_before><commit_msg>Test case for new `derive(PartialOrd)` expansion.<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.

// Issue 15523: derive(PartialOrd) should use the provided
// discriminant values for the derived ordering.

#[derive(PartialEq, PartialOrd)]
enum E1 {
    Pos2 = 2,
    Neg1 = -1,
    Pos1 = 1,
}

#[derive(PartialEq, PartialOrd)]
#[repr(u8)]
enum E2 {
    Pos2 = 2,
    PosMax = !0 as u8,
    Pos1 = 1,
}

#[derive(PartialEq, PartialOrd)]
#[repr(i8)]
enum E3 {
    Pos2 = 2,
    Neg1 = -1_i8,
    Pos1 = 1,
}

fn main() {
    assert!(E1::Pos2 > E1::Pos1);
    assert!(E1::Pos1 > E1::Neg1);
    assert!(E1::Pos2 > E1::Neg1);

    assert!(E2::Pos2 > E2::Pos1);
    assert!(E2::Pos1 < E2::PosMax);
    assert!(E2::Pos2 < E2::PosMax);

    assert!(E3::Pos2 > E3::Pos1);
    assert!(E3::Pos1 > E3::Neg1);
    assert!(E3::Pos2 > E3::Neg1);
}
<|endoftext|>


<commit_before>// A test of the macro system. Can we do HTML literals?

// xfail-pretty
// xfail-test

macro_rules! html {
    { $($body:tt)* } => {
        let builder = HTMLBuilder();
        build_html!{builder := $($body)*};
        builder.getDoc()
    }
}

macro_rules! build_html {
    { $builder:expr := </$tag:ident> $($rest:tt)* } => {
        $builder.endTag(stringify!($tag));
        build_html!{ $builder := $($rest)* };
    };

    { $builder:expr := <$tag:ident> $($rest:tt)* } => {
        $builder.beginTag(stringify!($tag));
        build_html!{ $builder := $($rest)* };
    };

    { $builder:expr := . $($rest:tt)* } => {
        $builder.addText(~".");
        build_html!{ $builder := $($rest)* };
    };

    { $builder:expr := $word:ident $($rest:tt)* } => {
        $builder.addText(stringify!($word));
        build_html!{ $builder := $($rest)* };
    };

    { $builder:expr := } => { }
}

fn main() {

    let page = html! {

            <title>This is the title.</title>

This is some text

    };

    // When we can do this, we are successful:
    //
    //let page = tag(~"html", ~[tag(~"head", ~[...])])

}

enum HTMLFragment {
}

struct HTMLBuilder {
    bar: ();
    fn getDoc() -> HTMLFragment { fail }
    fn beginTag(tag: ~str) { }
    fn endTag(tag: ~str) { }
    fn addText(test: ~str) { }
}

fn HTMLBuilder() -> HTMLBuilder {
    HTMLBuilder { bar: () }
}<commit_msg>A better HTML parser.<commit_after>// A test of the macro system. Can we do HTML literals?

// xfail-pretty

/*

This is an HTML parser written as a macro. It's all CPS, and we have
to carry around a bunch of state. The arguments to macros all look like this:

{ tag_stack* # expr* # tokens }

The stack keeps track of where we are in the tree. The expr is a list
of children of the current node. The tokens are everything that's
left.

*/

macro_rules! html {
    { $($body:tt)* } => (
        parse_node!( []; []; $($body)* )
    )
}

macro_rules! parse_node {
    {
        [:$head:ident ($(:$head_nodes:expr),*)
         $(:$tags:ident ($(:$tag_nodes:expr),*))*];
        [$(:$nodes:expr),*];
        </$tag:ident> $($rest:tt)*
    } => (
        parse_node!(
            [$(: $tags ($(:$tag_nodes),*))*];
            [$(:$head_nodes,)* :tag(stringify!($head), ~[$($nodes),*])];
            $($rest)*
        )
    );

    {
        [$(:$tags:ident ($(:$tag_nodes:expr),*) )*];
        [$(:$nodes:expr),*];
        <$tag:ident> $($rest:tt)*
    } => (
        parse_node!(
            [:$tag ($(:$nodes)*) $(: $tags ($(:$tag_nodes),*) )*];
            [];
            $($rest)*
        )
    );

    {
        [$(:$tags:ident ($(:$tag_nodes:expr),*) )*];
        [$(:$nodes:expr),*];
        . $($rest:tt)*
    } => (
        parse_node!(
            [$(: $tags ($(:$tag_nodes),*))*];
            [$(:$nodes,)* :text(~".")];
            $($rest)*
        )
    );

    {
        [$(:$tags:ident ($(:$tag_nodes:expr),*) )*];
        [$(:$nodes:expr),*];
        $word:ident $($rest:tt)*
    } => (
        parse_node!(
            [$(: $tags ($(:$tag_nodes),*))*];
            [$(:$nodes,)* :text(stringify!($word))];
            $($rest)*
        )
    );

    { []; [:$e:expr]; } => ( $e );
}

fn main() {
    let page = html! {

            <title>This is the title.</title>

This is some text

    };
}

enum HTMLFragment {
    tag(~str, ~[HTMLFragment]),
    text(~str),
}
<|endoftext|>


<commit_before><commit_msg>Remove unused code on Linux<commit_after><|endoftext|>


<commit_before><commit_msg>Fix reftest failure on AMD GPUs. Fixes #2642 (and probably #2064).<commit_after><|endoftext|>


<commit_before>// Copyright 2012-2014 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.

// Since we mark some ABIs as "nounwind" to LLVM, we must make sure that
// we never unwind through them.

// ignore-cloudabi no env and process
// ignore-emscripten no processes

use std::{env, panic};
use std::io::prelude::*;
use std::io;
use std::process::{Command, Stdio};

#[unwind(aborts)]
extern "C" fn panic_in_ffi() {
    panic!("Test");
}

fn test() {
    let _ = panic::catch_unwind(|| { panic_in_ffi(); });
    // The process should have aborted by now.
    io::stdout().write(b"This should never be printed.\n");
    let _ = io::stdout().flush();
}

fn main() {
    let args: Vec<String> = env::args().collect();
    if args.len() > 1 && args[1] == "test" {
        return test();
    }

    let mut p = Command::new(&args[0])
                        .stdout(Stdio::piped())
                        .stdin(Stdio::piped())
                        .arg("test").spawn().unwrap();
    assert!(!p.wait().unwrap().success());
}
<commit_msg>add `unwind_attributes` feature<commit_after>// Copyright 2012-2014 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.

// Since we mark some ABIs as "nounwind" to LLVM, we must make sure that
// we never unwind through them.

// ignore-cloudabi no env and process
// ignore-emscripten no processes

#![feature(unwind_attributes)]

use std::{env, panic};
use std::io::prelude::*;
use std::io;
use std::process::{Command, Stdio};

#[unwind(aborts)]
extern "C" fn panic_in_ffi() {
    panic!("Test");
}

fn test() {
    let _ = panic::catch_unwind(|| { panic_in_ffi(); });
    // The process should have aborted by now.
    io::stdout().write(b"This should never be printed.\n");
    let _ = io::stdout().flush();
}

fn main() {
    let args: Vec<String> = env::args().collect();
    if args.len() > 1 && args[1] == "test" {
        return test();
    }

    let mut p = Command::new(&args[0])
                        .stdout(Stdio::piped())
                        .stdin(Stdio::piped())
                        .arg("test").spawn().unwrap();
    assert!(!p.wait().unwrap().success());
}
<|endoftext|>


<commit_before><commit_msg>placeholder: ownership in Rust<commit_after>pub fn say(s: String) {
    println!("You know what? {}!", s)
}

fn main() {
    let a = String::from("Bananas");
    say(a.clone());
    println!("Damn right! {}!", a)
}
<|endoftext|>


<commit_before><commit_msg>Add code for role-playing-game<commit_after>pub struct Player {
    pub health: u32,
    pub mana: Option<u32>,
    pub level: u32,
}

impl Player {
    pub fn revive(&self) -> Option<Player> {
        if self.health != 0 {
            None
        } else {
            Some(Player {
                health: 100,
                mana: self.mana.map(|_| 100),
                ..*self
            })
        }
    }

    pub fn cast_spell(&mut self, mana_cost: u32) -> u32 {
        match &mut self.mana {
            None => {
                self.health -= mana_cost.min(self.health);
                0
            }
            Some(m) if *m >= mana_cost => {
                *m -= mana_cost;
                mana_cost * 2
            }
            Some(_) => 0,
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>[Rust] The benefit of never type<commit_after>use std::mem::size_of;

enum Never { }
struct ZeroSize;

type NeverFailResult<T> = Result<T, Never>;
type ZeroSizeResult<T> = Result<T, ZeroSize>;

fn main() {
    println!("{}", size_of::<u32>()); // 4
    println!("{}", size_of::<NeverFailResult<u32>>()); // 4
    println!("{}", size_of::<Option<u32>>()); // 8
    println!("{}", size_of::<NeverFailResult<Option<u32>>>()); // 8

    println!("{}", size_of::<u32>()); // 4
    println!("{}", size_of::<ZeroSizeResult<u32>>()); // 8
    println!("{}", size_of::<Option<u32>>()); // 8
    println!("{}", size_of::<ZeroSizeResult<Option<u32>>>()); // 8
}
<|endoftext|>


<commit_before><commit_msg>Implement Memory device.<commit_after><|endoftext|>


<commit_before><commit_msg>forget the --amend syntax<commit_after>//compute Jacobi symbol of a number

use super::Mod;
use std::collections::HashSet;

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
enum Jacobi {
    Value(i8),  // -1, 0, 1
    Frac{pos: bool, numer: u64, denom: u64},
}

impl Jacobi {
    fn from_val(a: i8) -> Jacobi {
        Jacobi::Value(a)
    }
    fn from_frac(s: bool, a: u64, b: u64) -> Jacobi {
        Jacobi::Frac{pos: s, numer: a, denom: b}
    }
    fn print(&self) {
        if let &Jacobi::Frac{pos: p, numer: n, denom: d} = self {
            println!(" {} J( {} / {} )",
                     if p { '+' } else { '-' }, n, d);
        } else if let &Jacobi::Value(v) = self {
            println!(" {} ", v)
        }
    }

    fn reduce(&self) -> Jacobi {
        //let reductions = vec![Jacobi::modulo, Jacobi::two_numer, Jacobi::reciprocal];
        let a = &Jacobi::modulo;
        let b = &Jacobi::two_numer;
        let c = &Jacobi::reciprocal;;
        let mut reductions: Vec<&Fn(&Jacobi) -> Option<Jacobi>> = Vec::new();
        reductions.push(a);
        reductions.push(b);
        reductions.push(c);

        let mut attempts: HashSet<Jacobi> = HashSet::new();

        loop {

        }
        Jacobi::Value(0)
    }

    //methods of reducing:
    fn modulo(&self) -> Option<Jacobi> {
        // if a≡b(mod p), L(a/p) = L(b/p)
        if let &Jacobi::Frac{pos: p, numer: n, denom: d} = self {
            Some(Jacobi::from_frac(p, n.modulo(d), d))
        } else {
            None
        }
    }
    fn two_numer(&self) -> Option<Jacobi> {
        // J((ab)/n) = J(a/n)*J(b/n)
        // J(2/n) = { 1 iff n≡±1(mod 8), -1 iff n≡ٍ±3(mod 8) }
        if let &Jacobi::Frac{pos: p, numer: n, denom: d} = self {
            let z = n.trailing_zeros();
            let n_ = n / 2u64.pow(z);
            let rem = d.modulo(8);
            let sign: i8 = {
                if rem == 1 || rem == 7 { 1 }
                else if rem == 3 || rem == 5 { -1 }
                else { return None }
            };
            let mut acc_sign = sign.pow(z);
            if !p { acc_sign *= -1; }
            Some(Jacobi::from_frac(acc_sign == 1, n, d))
        } else {
            None
        }
    }
    fn reciprocal(&self) -> Option<Jacobi> {
        // J(m/n) = {-J(n/m) if m≡n≡3(mod 4)
        if let &Jacobi::Frac{pos: p, numer: n, denom: d} = self {
            if n.modulo(4) == 3 && d.modulo(4) == 3 {
                Some(Jacobi::from_frac(!p, d, n))
            } else {
                None
            }
        } else {
            None
        }
    }

}
<|endoftext|>


<commit_before><commit_msg>also add an async fn test<commit_after>#![feature(
    async_await,
    await_macro,
    futures_api,
    pin,
)]

use std::{future::Future, pin::Pin, task::Poll};

// See if we can run a basic `async fn`
pub async fn foo(x: &u32, y: u32) -> u32 {
    let y = &y;
    let z = 9;
    let z = &z;
    let y = await!(async { *y + *z });
    let a = 10;
    let a = &a;
    *x + y + *a
}

fn main() {
    use std::{sync::Arc, task::{Wake, local_waker}};

    struct NoWake;
    impl Wake for NoWake {
        fn wake(_arc_self: &Arc<Self>) {
            panic!();
        }
    }

    let lw = unsafe { local_waker(Arc::new(NoWake)) };
    let x = 5;
    let mut fut = foo(&x, 7);
    assert_eq!(unsafe { Pin::new_unchecked(&mut fut) }.poll(&lw), Poll::Ready(31));
}
<|endoftext|>


<commit_before><commit_msg>rust automatically implements certain traits<commit_after><|endoftext|>


<commit_before><commit_msg>Improve stress test<commit_after><|endoftext|>


<commit_before><commit_msg>+ fastup preparation<commit_after>//! fastup: FAncy STatus markUP language
//!
//! hello [ff0000:world(0000ff:yes) or no] <time|hello|world> up

<|endoftext|>


<commit_before><commit_msg>Add rust code for rna-transcription<commit_after>#[derive(Debug, PartialEq)]
pub struct RibonucleicAcid(String);

impl RibonucleicAcid {
    pub fn new(serial: &str) -> RibonucleicAcid {
        RibonucleicAcid(serial.to_string())
    }
}

#[derive(Debug, PartialEq)]
pub struct DeoxyribonucleicAcid(String);

impl DeoxyribonucleicAcid {
    pub fn new(serial: &str) -> DeoxyribonucleicAcid {
        DeoxyribonucleicAcid(serial.to_string())
    }

    pub fn to_rna(&self) -> Result<RibonucleicAcid, String> {
        let rna = self.0
            .chars()
            .filter_map(|c| match c {
                'A' => Some('U'),
                'C' => Some('G'),
                'G' => Some('C'),
                'T' => Some('A'),
                _ => None,
            })
            .collect::<String>();

        if rna.len() != self.0.len() {
            return Err("Invalid DNA serial".to_string());
        }

        Ok(RibonucleicAcid(rna))
    }
}
<|endoftext|>