<commit_before>extern crate compiletest_rs as compiletest;

use std::path::{PathBuf, Path};
use std::io::Write;

fn compile_fail(sysroot: &Path) {
    let flags = format!("--sysroot {} -Dwarnings", sysroot.to_str().expect("non utf8 path"));
    for_all_targets(&sysroot, |target| {
        let mut config = compiletest::default_config();
        config.host_rustcflags = Some(flags.clone());
        config.mode = "compile-fail".parse().expect("Invalid mode");
        config.run_lib_path = Path::new(sysroot).join("lib").join("rustlib").join(&target).join("lib");
        config.rustc_path = "target/debug/miri".into();
        config.src_base = PathBuf::from("tests/compile-fail".to_string());
        config.target = target.to_owned();
        config.target_rustcflags = Some(flags.clone());
        compiletest::run_tests(&config);
    });
}

fn run_pass() {
    let mut config = compiletest::default_config();
    config.mode = "run-pass".parse().expect("Invalid mode");
    config.src_base = PathBuf::from("tests/run-pass".to_string());
    config.target_rustcflags = Some("-Dwarnings".to_string());
    config.host_rustcflags = Some("-Dwarnings".to_string());
    compiletest::run_tests(&config);
}

fn miri_pass(path: &str, target: &str, host: &str) {
    let mut config = compiletest::default_config();
    config.mode = "mir-opt".parse().expect("Invalid mode");
    config.src_base = PathBuf::from(path);
    config.target = target.to_owned();
    config.host = host.to_owned();
    config.rustc_path = PathBuf::from("target/debug/miri");
    // don't actually execute the final binary, it might be for other targets and we only care
    // about running miri, not the binary.
    config.runtool = Some("echo \"\" || ".to_owned());
    if target == host {
        std::env::set_var("MIRI_HOST_TARGET", "yes");
    }
    compiletest::run_tests(&config);
    std::env::set_var("MIRI_HOST_TARGET", "");
}

fn is_target_dir<P: Into<PathBuf>>(path: P) -> bool {
    let mut path = path.into();
    path.push("lib");
    path.metadata().map(|m| m.is_dir()).unwrap_or(false)
}

fn for_all_targets<F: FnMut(String)>(sysroot: &Path, mut f: F) {
    let target_dir = sysroot.join("lib").join("rustlib");
    println!("target dir: {}", target_dir.to_str().unwrap());
    for entry in std::fs::read_dir(target_dir).expect("invalid sysroot") {
        let entry = entry.unwrap();
        if !is_target_dir(entry.path()) { continue; }
        let target = entry.file_name().into_string().unwrap();
        let stderr = std::io::stderr();
        writeln!(stderr.lock(), "running tests for target {}", target).unwrap();
        f(target);
    }
}

#[test]
fn compile_test() {
    let sysroot = std::process::Command::new("rustc")
        .arg("--print")
        .arg("sysroot")
        .output()
        .expect("rustc not found")
        .stdout;
    let sysroot = std::str::from_utf8(&sysroot).expect("sysroot is not utf8").trim();
    let sysroot = &Path::new(&sysroot);
    let host = std::process::Command::new("rustc")
        .arg("-vV")
        .output()
        .expect("rustc not found for -vV")
        .stdout;
    let host = std::str::from_utf8(&host).expect("sysroot is not utf8");
    let host = host.split("\nhost: ").skip(1).next().expect("no host: part in rustc -vV");
    let host = host.split("\n").next().expect("no \n after host");

    if let Ok(path) = std::env::var("MIRI_RUSTC_TEST") {
        let mut mir_not_found = Vec::new();
        let mut crate_not_found = Vec::new();
        let mut success = 0;
        let mut failed = Vec::new();
        let mut c_abi_fns = Vec::new();
        let mut abi = Vec::new();
        let mut unsupported = Vec::new();
        let mut unimplemented_intrinsic = Vec::new();
        let mut limits = Vec::new();
        for file in std::fs::read_dir(path).unwrap() {
            let file = file.unwrap();
            let path = file.path();
            if !file.metadata().unwrap().is_file() || !path.to_str().unwrap().ends_with(".rs") {
                continue;
            }
            let stderr = std::io::stderr();
            write!(stderr.lock(), "test [miri-pass] {} ... ", path.display()).unwrap();
            let mut cmd = std::process::Command::new("target/debug/miri");
            cmd.arg(path);
            let libs = Path::new(&sysroot).join("lib");
            let sysroot = libs.join("rustlib").join(&host).join("lib");
            let paths = std::env::join_paths(&[libs, sysroot]).unwrap();
            cmd.env(compiletest::procsrv::dylib_env_var(), paths);

            match cmd.output() {
                Ok(ref output) if output.status.success() => {
                    success += 1;
                    writeln!(stderr.lock(), "ok").unwrap()
                },
                Ok(output) => {
                    let output_err = std::str::from_utf8(&output.stderr).unwrap();
                    if let Some(text) = output_err.splitn(2, "no mir for `").nth(1) {
                        let end = text.find('`').unwrap();
                        mir_not_found.push(text[..end].to_string());
                        writeln!(stderr.lock(), "NO MIR FOR `{}`", &text[..end]).unwrap();
                    } else if let Some(text) = output_err.splitn(2, "can't find crate for `").nth(1) {
                        let end = text.find('`').unwrap();
                        crate_not_found.push(text[..end].to_string());
                        writeln!(stderr.lock(), "CAN'T FIND CRATE FOR `{}`", &text[..end]).unwrap();
                    } else {
                        for text in output_err.split("error: ").skip(1) {
                            let end = text.find('\n').unwrap_or(text.len());
                            let c_abi = "can't call C ABI function: ";
                            let unimplemented_intrinsic_s = "unimplemented intrinsic: ";
                            let unsupported_s = "miri does not support ";
                            let abi_s = "can't handle function with ";
                            let limit_s = "reached the configured maximum ";
                            if text.starts_with(c_abi) {
                                c_abi_fns.push(text[c_abi.len()..end].to_string());
                            } else if text.starts_with(unimplemented_intrinsic_s) {
                                unimplemented_intrinsic.push(text[unimplemented_intrinsic_s.len()..end].to_string());
                            } else if text.starts_with(unsupported_s) {
                                unsupported.push(text[unsupported_s.len()..end].to_string());
                            } else if text.starts_with(abi_s) {
                                abi.push(text[abi_s.len()..end].to_string());
                            } else if text.starts_with(limit_s) {
                                limits.push(text[limit_s.len()..end].to_string());
                            } else {
                                if text.find("aborting").is_none() {
                                    failed.push(text[..end].to_string());
                                }
                            }
                        }
                        writeln!(stderr.lock(), "FAILED with exit code {:?}", output.status.code()).unwrap();
                        writeln!(stderr.lock(), "stdout: \n {}", std::str::from_utf8(&output.stdout).unwrap()).unwrap();
                        writeln!(stderr.lock(), "stderr: \n {}", output_err).unwrap();
                    }
                }
                Err(e) => {
                    writeln!(stderr.lock(), "FAILED: {}", e).unwrap();
                    panic!("failed to execute miri");
                },
            }
        }
        let stderr = std::io::stderr();
        let mut stderr = stderr.lock();
        writeln!(stderr, "{} success, {} no mir, {} crate not found, {} failed, \
                          {} C fn, {} ABI, {} unsupported, {} intrinsic",
                          success, mir_not_found.len(), crate_not_found.len(), failed.len(),
                          c_abi_fns.len(), abi.len(), unsupported.len(), unimplemented_intrinsic.len()).unwrap();
        writeln!(stderr, "# The \"other reasons\" errors").unwrap();
        writeln!(stderr, "(sorted, deduplicated)").unwrap();
        print_vec(&mut stderr, failed);

        writeln!(stderr, "# can't call C ABI function").unwrap();
        print_vec(&mut stderr, c_abi_fns);

        writeln!(stderr, "# unsupported ABI").unwrap();
        print_vec(&mut stderr, abi);

        writeln!(stderr, "# unsupported").unwrap();
        print_vec(&mut stderr, unsupported);

        writeln!(stderr, "# unimplemented intrinsics").unwrap();
        print_vec(&mut stderr, unimplemented_intrinsic);

        writeln!(stderr, "# mir not found").unwrap();
        print_vec(&mut stderr, mir_not_found);

        writeln!(stderr, "# crate not found").unwrap();
        print_vec(&mut stderr, crate_not_found);

        panic!("ran miri on rustc test suite. Test failing for convenience");
    } else {
        run_pass();
        for_all_targets(&sysroot, |target| {
            miri_pass("tests/run-pass", &target, host);
        });
        compile_fail(&sysroot);
    }
}

fn print_vec<W: std::io::Write>(stderr: &mut W, v: Vec<String>) {
    writeln!(stderr, "```").unwrap();
    for (n, s) in vec_to_hist(v).into_iter().rev() {
        writeln!(stderr, "{:4} {}", n, s).unwrap();
    }
    writeln!(stderr, "```").unwrap();
}

fn vec_to_hist<T: PartialEq + Ord>(mut v: Vec<T>) -> Vec<(usize, T)> {
    v.sort();
    let mut v = v.into_iter();
    let mut result = Vec::new();
    let mut current = v.next();
    'outer: while let Some(current_val) = current {
        let mut n = 1;
        while let Some(next) = v.next() {
            if next == current_val {
                n += 1;
            } else {
                result.push((n, current_val));
                current = Some(next);
                continue 'outer;
            }
        }
        result.push((n, current_val));
        break;
    }
    result.sort();
    result
}
<commit_msg>Also test subdirectories of `rust/src/test/run-pass`<commit_after>extern crate compiletest_rs as compiletest;

use std::path::{PathBuf, Path};
use std::io::Write;

fn compile_fail(sysroot: &Path) {
    let flags = format!("--sysroot {} -Dwarnings", sysroot.to_str().expect("non utf8 path"));
    for_all_targets(&sysroot, |target| {
        let mut config = compiletest::default_config();
        config.host_rustcflags = Some(flags.clone());
        config.mode = "compile-fail".parse().expect("Invalid mode");
        config.run_lib_path = Path::new(sysroot).join("lib").join("rustlib").join(&target).join("lib");
        config.rustc_path = "target/debug/miri".into();
        config.src_base = PathBuf::from("tests/compile-fail".to_string());
        config.target = target.to_owned();
        config.target_rustcflags = Some(flags.clone());
        compiletest::run_tests(&config);
    });
}

fn run_pass() {
    let mut config = compiletest::default_config();
    config.mode = "run-pass".parse().expect("Invalid mode");
    config.src_base = PathBuf::from("tests/run-pass".to_string());
    config.target_rustcflags = Some("-Dwarnings".to_string());
    config.host_rustcflags = Some("-Dwarnings".to_string());
    compiletest::run_tests(&config);
}

fn miri_pass(path: &str, target: &str, host: &str) {
    let mut config = compiletest::default_config();
    config.mode = "mir-opt".parse().expect("Invalid mode");
    config.src_base = PathBuf::from(path);
    config.target = target.to_owned();
    config.host = host.to_owned();
    config.rustc_path = PathBuf::from("target/debug/miri");
    // don't actually execute the final binary, it might be for other targets and we only care
    // about running miri, not the binary.
    config.runtool = Some("echo \"\" || ".to_owned());
    if target == host {
        std::env::set_var("MIRI_HOST_TARGET", "yes");
    }
    compiletest::run_tests(&config);
    std::env::set_var("MIRI_HOST_TARGET", "");
}

fn is_target_dir<P: Into<PathBuf>>(path: P) -> bool {
    let mut path = path.into();
    path.push("lib");
    path.metadata().map(|m| m.is_dir()).unwrap_or(false)
}

fn for_all_targets<F: FnMut(String)>(sysroot: &Path, mut f: F) {
    let target_dir = sysroot.join("lib").join("rustlib");
    println!("target dir: {}", target_dir.to_str().unwrap());
    for entry in std::fs::read_dir(target_dir).expect("invalid sysroot") {
        let entry = entry.unwrap();
        if !is_target_dir(entry.path()) { continue; }
        let target = entry.file_name().into_string().unwrap();
        let stderr = std::io::stderr();
        writeln!(stderr.lock(), "running tests for target {}", target).unwrap();
        f(target);
    }
}

#[test]
fn compile_test() {
    let sysroot = std::process::Command::new("rustc")
        .arg("--print")
        .arg("sysroot")
        .output()
        .expect("rustc not found")
        .stdout;
    let sysroot = std::str::from_utf8(&sysroot).expect("sysroot is not utf8").trim();
    let sysroot = &Path::new(&sysroot);
    let host = std::process::Command::new("rustc")
        .arg("-vV")
        .output()
        .expect("rustc not found for -vV")
        .stdout;
    let host = std::str::from_utf8(&host).expect("sysroot is not utf8");
    let host = host.split("\nhost: ").skip(1).next().expect("no host: part in rustc -vV");
    let host = host.split("\n").next().expect("no \n after host");

    if let Ok(path) = std::env::var("MIRI_RUSTC_TEST") {
        let mut mir_not_found = Vec::new();
        let mut crate_not_found = Vec::new();
        let mut success = 0;
        let mut failed = Vec::new();
        let mut c_abi_fns = Vec::new();
        let mut abi = Vec::new();
        let mut unsupported = Vec::new();
        let mut unimplemented_intrinsic = Vec::new();
        let mut limits = Vec::new();
        let mut files: Vec<_> = std::fs::read_dir(path).unwrap().collect();
        while let Some(file) = files.pop() {
            let file = file.unwrap();
            let path = file.path();
            if file.metadata().unwrap().is_dir() {
                if !path.to_str().unwrap().ends_with("auxiliary") {
                    // add subdirs recursively
                    files.extend(std::fs::read_dir(path).unwrap());
                }
                continue;
            }
            if !file.metadata().unwrap().is_file() || !path.to_str().unwrap().ends_with(".rs") {
                continue;
            }
            let stderr = std::io::stderr();
            write!(stderr.lock(), "test [miri-pass] {} ... ", path.display()).unwrap();
            let mut cmd = std::process::Command::new("target/debug/miri");
            cmd.arg(path);
            let libs = Path::new(&sysroot).join("lib");
            let sysroot = libs.join("rustlib").join(&host).join("lib");
            let paths = std::env::join_paths(&[libs, sysroot]).unwrap();
            cmd.env(compiletest::procsrv::dylib_env_var(), paths);

            match cmd.output() {
                Ok(ref output) if output.status.success() => {
                    success += 1;
                    writeln!(stderr.lock(), "ok").unwrap()
                },
                Ok(output) => {
                    let output_err = std::str::from_utf8(&output.stderr).unwrap();
                    if let Some(text) = output_err.splitn(2, "no mir for `").nth(1) {
                        let end = text.find('`').unwrap();
                        mir_not_found.push(text[..end].to_string());
                        writeln!(stderr.lock(), "NO MIR FOR `{}`", &text[..end]).unwrap();
                    } else if let Some(text) = output_err.splitn(2, "can't find crate for `").nth(1) {
                        let end = text.find('`').unwrap();
                        crate_not_found.push(text[..end].to_string());
                        writeln!(stderr.lock(), "CAN'T FIND CRATE FOR `{}`", &text[..end]).unwrap();
                    } else {
                        for text in output_err.split("error: ").skip(1) {
                            let end = text.find('\n').unwrap_or(text.len());
                            let c_abi = "can't call C ABI function: ";
                            let unimplemented_intrinsic_s = "unimplemented intrinsic: ";
                            let unsupported_s = "miri does not support ";
                            let abi_s = "can't handle function with ";
                            let limit_s = "reached the configured maximum ";
                            if text.starts_with(c_abi) {
                                c_abi_fns.push(text[c_abi.len()..end].to_string());
                            } else if text.starts_with(unimplemented_intrinsic_s) {
                                unimplemented_intrinsic.push(text[unimplemented_intrinsic_s.len()..end].to_string());
                            } else if text.starts_with(unsupported_s) {
                                unsupported.push(text[unsupported_s.len()..end].to_string());
                            } else if text.starts_with(abi_s) {
                                abi.push(text[abi_s.len()..end].to_string());
                            } else if text.starts_with(limit_s) {
                                limits.push(text[limit_s.len()..end].to_string());
                            } else {
                                if text.find("aborting").is_none() {
                                    failed.push(text[..end].to_string());
                                }
                            }
                        }
                        writeln!(stderr.lock(), "FAILED with exit code {:?}", output.status.code()).unwrap();
                        writeln!(stderr.lock(), "stdout: \n {}", std::str::from_utf8(&output.stdout).unwrap()).unwrap();
                        writeln!(stderr.lock(), "stderr: \n {}", output_err).unwrap();
                    }
                }
                Err(e) => {
                    writeln!(stderr.lock(), "FAILED: {}", e).unwrap();
                    panic!("failed to execute miri");
                },
            }
        }
        let stderr = std::io::stderr();
        let mut stderr = stderr.lock();
        writeln!(stderr, "{} success, {} no mir, {} crate not found, {} failed, \
                          {} C fn, {} ABI, {} unsupported, {} intrinsic",
                          success, mir_not_found.len(), crate_not_found.len(), failed.len(),
                          c_abi_fns.len(), abi.len(), unsupported.len(), unimplemented_intrinsic.len()).unwrap();
        writeln!(stderr, "# The \"other reasons\" errors").unwrap();
        writeln!(stderr, "(sorted, deduplicated)").unwrap();
        print_vec(&mut stderr, failed);

        writeln!(stderr, "# can't call C ABI function").unwrap();
        print_vec(&mut stderr, c_abi_fns);

        writeln!(stderr, "# unsupported ABI").unwrap();
        print_vec(&mut stderr, abi);

        writeln!(stderr, "# unsupported").unwrap();
        print_vec(&mut stderr, unsupported);

        writeln!(stderr, "# unimplemented intrinsics").unwrap();
        print_vec(&mut stderr, unimplemented_intrinsic);

        writeln!(stderr, "# mir not found").unwrap();
        print_vec(&mut stderr, mir_not_found);

        writeln!(stderr, "# crate not found").unwrap();
        print_vec(&mut stderr, crate_not_found);

        panic!("ran miri on rustc test suite. Test failing for convenience");
    } else {
        run_pass();
        for_all_targets(&sysroot, |target| {
            miri_pass("tests/run-pass", &target, host);
        });
        compile_fail(&sysroot);
    }
}

fn print_vec<W: std::io::Write>(stderr: &mut W, v: Vec<String>) {
    writeln!(stderr, "```").unwrap();
    for (n, s) in vec_to_hist(v).into_iter().rev() {
        writeln!(stderr, "{:4} {}", n, s).unwrap();
    }
    writeln!(stderr, "```").unwrap();
}

fn vec_to_hist<T: PartialEq + Ord>(mut v: Vec<T>) -> Vec<(usize, T)> {
    v.sort();
    let mut v = v.into_iter();
    let mut result = Vec::new();
    let mut current = v.next();
    'outer: while let Some(current_val) = current {
        let mut n = 1;
        while let Some(next) = v.next() {
            if next == current_val {
                n += 1;
            } else {
                result.push((n, current_val));
                current = Some(next);
                continue 'outer;
            }
        }
        result.push((n, current_val));
        break;
    }
    result.sort();
    result
}
<|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.

//! Validates all used crates and extern libraries and loads their metadata

use core::prelude::*;

use metadata::cstore;
use metadata::common::*;
use metadata::decoder;
use metadata::filesearch::FileSearch;
use metadata::loader;

use core::either;
use core::option;
use core::vec;
use syntax::attr;
use syntax::codemap::{span, dummy_sp};
use syntax::diagnostic::span_handler;
use syntax::parse::token::ident_interner;
use syntax::print::pprust;
use syntax::visit;
use syntax::{ast, ast_util};
use std::oldmap::HashMap;

// Traverses an AST, reading all the information about use'd crates and extern
// libraries necessary for later resolving, typechecking, linking, etc.
pub fn read_crates(diag: span_handler,
                   crate: ast::crate,
                   cstore: @mut cstore::CStore,
                   filesearch: FileSearch,
                   os: loader::os,
                   statik: bool,
                   intr: @ident_interner) {
    let e = @mut Env {
        diag: diag,
        filesearch: filesearch,
        cstore: cstore,
        os: os,
        statik: statik,
        crate_cache: @mut ~[],
        next_crate_num: 1,
        intr: intr
    };
    let v =
        visit::mk_simple_visitor(@visit::SimpleVisitor {
            visit_view_item: |a| visit_view_item(e, a),
            visit_item: |a| visit_item(e, a),
            .. *visit::default_simple_visitor()});
    visit::visit_crate(crate, (), v);
    dump_crates(e.crate_cache);
    warn_if_multiple_versions(e, diag, e.crate_cache);
}

type cache_entry = {
    cnum: int,
    span: span,
    hash: ~str,
    metas: @~[@ast::meta_item]
};

fn dump_crates(+crate_cache: @mut ~[cache_entry]) {
    debug!("resolved crates:");
    for crate_cache.each |entry| {
        debug!("cnum: %?", entry.cnum);
        debug!("span: %?", entry.span);
        debug!("hash: %?", entry.hash);
    }
}

fn warn_if_multiple_versions(e: @mut Env,
                             diag: span_handler,
                             crate_cache: @mut ~[cache_entry]) {
    use either::*;

    if crate_cache.len() != 0u {
        let name = loader::crate_name_from_metas(
            /*bad*/copy *crate_cache.last().metas);
        let (matches, non_matches) =
            partition(crate_cache.map_to_vec(|&entry| {
                let othername = loader::crate_name_from_metas(
                    copy *entry.metas);
                if name == othername {
                    Left(entry)
                } else {
                    Right(entry)
                }
            }));

        assert !matches.is_empty();

        if matches.len() != 1u {
            diag.handler().warn(
                fmt!("using multiple versions of crate `%s`", name));
            for matches.each |match_| {
                diag.span_note(match_.span, ~"used here");
                let attrs = ~[
                    attr::mk_attr(attr::mk_list_item(
                        ~"link", /*bad*/copy *match_.metas))
                ];
                loader::note_linkage_attrs(e.intr, diag, attrs);
            }
        }

        warn_if_multiple_versions(e, diag, @mut non_matches);
    }
}

struct Env {
    diag: span_handler,
    filesearch: FileSearch,
    cstore: @mut cstore::CStore,
    os: loader::os,
    statik: bool,
    crate_cache: @mut ~[cache_entry],
    next_crate_num: ast::crate_num,
    intr: @ident_interner
}

fn visit_view_item(e: @mut Env, i: @ast::view_item) {
    match /*bad*/copy i.node {
      ast::view_item_use(ident, meta_items, id) => {
        debug!("resolving use stmt. ident: %?, meta: %?", ident, meta_items);
        let cnum = resolve_crate(e, ident, meta_items, ~"", i.span);
        cstore::add_use_stmt_cnum(e.cstore, id, cnum);
      }
      _ => ()
    }
}

fn visit_item(e: @mut Env, i: @ast::item) {
    match /*bad*/copy i.node {
      ast::item_foreign_mod(fm) => {
        match attr::foreign_abi(i.attrs) {
          either::Right(abi) => {
            if abi != ast::foreign_abi_cdecl &&
               abi != ast::foreign_abi_stdcall { return; }
          }
          either::Left(ref msg) => e.diag.span_fatal(i.span, (*msg))
        }

        let cstore = e.cstore;
        let mut already_added = false;
        let link_args = attr::find_attrs_by_name(i.attrs, "link_args");

        match fm.sort {
          ast::named => {
            let foreign_name =
               match attr::first_attr_value_str_by_name(i.attrs,
                                                        ~"link_name") {
                 Some(ref nn) => {
                   if (*nn) == ~"" {
                      e.diag.span_fatal(
                          i.span,
                          ~"empty #[link_name] not allowed; use #[nolink].");
                   }
                   (/*bad*/copy *nn)
                 }
                None => /*bad*/copy *e.intr.get(i.ident)
            };
            if attr::find_attrs_by_name(i.attrs, ~"nolink").is_empty() {
                already_added =
                    !cstore::add_used_library(cstore, copy foreign_name);
            }
            if !link_args.is_empty() && already_added {
                e.diag.span_fatal(i.span, ~"library '" + foreign_name +
                           ~"' already added: can't specify link_args.");
            }
          }
          ast::anonymous => { /* do nothing */ }
        }

        for link_args.each |a| {
            match attr::get_meta_item_value_str(attr::attr_meta(*a)) {
              Some(ref linkarg) => {
                cstore::add_used_link_args(cstore, (/*bad*/copy *linkarg));
              }
              None => {/* fallthrough */ }
            }
        }
      }
      _ => { }
    }
}

fn metas_with(+ident: ~str, +key: ~str, +metas: ~[@ast::meta_item])
    -> ~[@ast::meta_item] {
    let name_items = attr::find_meta_items_by_name(metas, key);
    if name_items.is_empty() {
        vec::append_one(metas, attr::mk_name_value_item_str(key, ident))
    } else {
        metas
    }
}

fn metas_with_ident(+ident: ~str, +metas: ~[@ast::meta_item])
    -> ~[@ast::meta_item] {
    metas_with(ident, ~"name", metas)
}

fn existing_match(e: @mut Env, metas: ~[@ast::meta_item], hash: ~str)
               -> Option<int> {
    for e.crate_cache.each |c| {
        if loader::metadata_matches(*c.metas, metas)
            && (hash.is_empty() || c.hash == hash) {
            return Some(c.cnum);
        }
    }
    return None;
}

fn resolve_crate(e: @mut Env,
                 ident: ast::ident,
                 +metas: ~[@ast::meta_item],
                 +hash: ~str,
                 span: span)
              -> ast::crate_num {
    let metas = metas_with_ident(/*bad*/copy *e.intr.get(ident), metas);

    match existing_match(e, metas, hash) {
      None => {
        let load_ctxt: loader::ctxt = {
            diag: e.diag,
            filesearch: e.filesearch,
            span: span,
            ident: ident,
            metas: metas,
            hash: hash,
            os: e.os,
            static: e.statik,
            intr: e.intr
        };
        let cinfo = loader::load_library_crate(load_ctxt);

        let cfilename = Path(cinfo.ident);
        let cdata = cinfo.data;

        let attrs = decoder::get_crate_attributes(cdata);
        let linkage_metas = attr::find_linkage_metas(attrs);
        let hash = decoder::get_crate_hash(cdata);

        // Claim this crate number and cache it
        let cnum = e.next_crate_num;
        e.crate_cache.push({cnum: cnum, span: span,
                            hash: hash, metas: @linkage_metas});
        e.next_crate_num += 1;

        // Now resolve the crates referenced by this crate
        let cnum_map = resolve_crate_deps(e, cdata);

        let cname =
            match attr::last_meta_item_value_str_by_name(load_ctxt.metas,
                                                         ~"name") {
              option::Some(ref v) => (/*bad*/copy *v),
              option::None => /*bad*/copy *e.intr.get(ident)
            };
        let cmeta = @{name: cname, data: cdata,
                      cnum_map: cnum_map, cnum: cnum};

        let cstore = e.cstore;
        cstore::set_crate_data(cstore, cnum, cmeta);
        cstore::add_used_crate_file(cstore, &cfilename);
        return cnum;
      }
      Some(cnum) => {
        return cnum;
      }
    }
}

// Go through the crate metadata and load any crates that it references
fn resolve_crate_deps(e: @mut Env, cdata: @~[u8]) -> cstore::cnum_map {
    debug!("resolving deps of external crate");
    // The map from crate numbers in the crate we're resolving to local crate
    // numbers
    let cnum_map = HashMap();
    for decoder::get_crate_deps(e.intr, cdata).each |dep| {
        let extrn_cnum = dep.cnum;
        let cname = dep.name;
        let cmetas = metas_with(/*bad*/copy dep.vers, ~"vers", ~[]);
        debug!("resolving dep crate %s ver: %s hash: %s",
               *e.intr.get(dep.name), dep.vers, dep.hash);
        match existing_match(e, metas_with_ident(copy *e.intr.get(cname),
                                                 copy cmetas),
                             dep.hash) {
          Some(local_cnum) => {
            debug!("already have it");
            // We've already seen this crate
            cnum_map.insert(extrn_cnum, local_cnum);
          }
          None => {
            debug!("need to load it");
            // This is a new one so we've got to load it
            // FIXME (#2404): Need better error reporting than just a bogus
            // span.
            let fake_span = dummy_sp();
            let local_cnum = resolve_crate(e, cname, cmetas,
                                           /*bad*/copy dep.hash, fake_span);
            cnum_map.insert(extrn_cnum, local_cnum);
          }
        }
    }
    return cnum_map;
}

// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<commit_msg>Support link_args at the crate level. Closes #1301<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.

//! Validates all used crates and extern libraries and loads their metadata

use core::prelude::*;

use metadata::cstore;
use metadata::common::*;
use metadata::decoder;
use metadata::filesearch::FileSearch;
use metadata::loader;

use core::either;
use core::option;
use core::vec;
use syntax::attr;
use syntax::codemap::{span, dummy_sp};
use syntax::diagnostic::span_handler;
use syntax::parse::token::ident_interner;
use syntax::print::pprust;
use syntax::visit;
use syntax::{ast, ast_util};
use std::oldmap::HashMap;

// Traverses an AST, reading all the information about use'd crates and extern
// libraries necessary for later resolving, typechecking, linking, etc.
pub fn read_crates(diag: span_handler,
                   crate: ast::crate,
                   cstore: @mut cstore::CStore,
                   filesearch: FileSearch,
                   os: loader::os,
                   statik: bool,
                   intr: @ident_interner) {
    let e = @mut Env {
        diag: diag,
        filesearch: filesearch,
        cstore: cstore,
        os: os,
        statik: statik,
        crate_cache: @mut ~[],
        next_crate_num: 1,
        intr: intr
    };
    let v =
        visit::mk_simple_visitor(@visit::SimpleVisitor {
            visit_view_item: |a| visit_view_item(e, a),
            visit_item: |a| visit_item(e, a),
            .. *visit::default_simple_visitor()});
    visit_crate(e, crate);
    visit::visit_crate(crate, (), v);
    dump_crates(e.crate_cache);
    warn_if_multiple_versions(e, diag, e.crate_cache);
}

type cache_entry = {
    cnum: int,
    span: span,
    hash: ~str,
    metas: @~[@ast::meta_item]
};

fn dump_crates(+crate_cache: @mut ~[cache_entry]) {
    debug!("resolved crates:");
    for crate_cache.each |entry| {
        debug!("cnum: %?", entry.cnum);
        debug!("span: %?", entry.span);
        debug!("hash: %?", entry.hash);
    }
}

fn warn_if_multiple_versions(e: @mut Env,
                             diag: span_handler,
                             crate_cache: @mut ~[cache_entry]) {
    use either::*;

    if crate_cache.len() != 0u {
        let name = loader::crate_name_from_metas(
            /*bad*/copy *crate_cache.last().metas);
        let (matches, non_matches) =
            partition(crate_cache.map_to_vec(|&entry| {
                let othername = loader::crate_name_from_metas(
                    copy *entry.metas);
                if name == othername {
                    Left(entry)
                } else {
                    Right(entry)
                }
            }));

        assert !matches.is_empty();

        if matches.len() != 1u {
            diag.handler().warn(
                fmt!("using multiple versions of crate `%s`", name));
            for matches.each |match_| {
                diag.span_note(match_.span, ~"used here");
                let attrs = ~[
                    attr::mk_attr(attr::mk_list_item(
                        ~"link", /*bad*/copy *match_.metas))
                ];
                loader::note_linkage_attrs(e.intr, diag, attrs);
            }
        }

        warn_if_multiple_versions(e, diag, @mut non_matches);
    }
}

struct Env {
    diag: span_handler,
    filesearch: FileSearch,
    cstore: @mut cstore::CStore,
    os: loader::os,
    statik: bool,
    crate_cache: @mut ~[cache_entry],
    next_crate_num: ast::crate_num,
    intr: @ident_interner
}

fn visit_crate(e: @mut Env, c: ast::crate) {
    let cstore = e.cstore;
    let link_args = attr::find_attrs_by_name(c.node.attrs, "link_args");

    for link_args.each |a| {
        match attr::get_meta_item_value_str(attr::attr_meta(*a)) {
          Some(ref linkarg) => {
            cstore::add_used_link_args(cstore, (/*bad*/copy *linkarg));
          }
          None => {/* fallthrough */ }
        }
    }
}

fn visit_view_item(e: @mut Env, i: @ast::view_item) {
    match /*bad*/copy i.node {
      ast::view_item_use(ident, meta_items, id) => {
        debug!("resolving use stmt. ident: %?, meta: %?", ident, meta_items);
        let cnum = resolve_crate(e, ident, meta_items, ~"", i.span);
        cstore::add_use_stmt_cnum(e.cstore, id, cnum);
      }
      _ => ()
    }
}

fn visit_item(e: @mut Env, i: @ast::item) {
    match /*bad*/copy i.node {
      ast::item_foreign_mod(fm) => {
        match attr::foreign_abi(i.attrs) {
          either::Right(abi) => {
            if abi != ast::foreign_abi_cdecl &&
               abi != ast::foreign_abi_stdcall { return; }
          }
          either::Left(ref msg) => e.diag.span_fatal(i.span, (*msg))
        }

        let cstore = e.cstore;
        let mut already_added = false;
        let link_args = attr::find_attrs_by_name(i.attrs, "link_args");

        match fm.sort {
          ast::named => {
            let foreign_name =
               match attr::first_attr_value_str_by_name(i.attrs,
                                                        ~"link_name") {
                 Some(ref nn) => {
                   if (*nn) == ~"" {
                      e.diag.span_fatal(
                          i.span,
                          ~"empty #[link_name] not allowed; use #[nolink].");
                   }
                   (/*bad*/copy *nn)
                 }
                None => /*bad*/copy *e.intr.get(i.ident)
            };
            if attr::find_attrs_by_name(i.attrs, ~"nolink").is_empty() {
                already_added =
                    !cstore::add_used_library(cstore, copy foreign_name);
            }
            if !link_args.is_empty() && already_added {
                e.diag.span_fatal(i.span, ~"library '" + foreign_name +
                           ~"' already added: can't specify link_args.");
            }
          }
          ast::anonymous => { /* do nothing */ }
        }

        for link_args.each |a| {
            match attr::get_meta_item_value_str(attr::attr_meta(*a)) {
              Some(ref linkarg) => {
                cstore::add_used_link_args(cstore, (/*bad*/copy *linkarg));
              }
              None => {/* fallthrough */ }
            }
        }
      }
      _ => { }
    }
}

fn metas_with(+ident: ~str, +key: ~str, +metas: ~[@ast::meta_item])
    -> ~[@ast::meta_item] {
    let name_items = attr::find_meta_items_by_name(metas, key);
    if name_items.is_empty() {
        vec::append_one(metas, attr::mk_name_value_item_str(key, ident))
    } else {
        metas
    }
}

fn metas_with_ident(+ident: ~str, +metas: ~[@ast::meta_item])
    -> ~[@ast::meta_item] {
    metas_with(ident, ~"name", metas)
}

fn existing_match(e: @mut Env, metas: ~[@ast::meta_item], hash: ~str)
               -> Option<int> {
    for e.crate_cache.each |c| {
        if loader::metadata_matches(*c.metas, metas)
            && (hash.is_empty() || c.hash == hash) {
            return Some(c.cnum);
        }
    }
    return None;
}

fn resolve_crate(e: @mut Env,
                 ident: ast::ident,
                 +metas: ~[@ast::meta_item],
                 +hash: ~str,
                 span: span)
              -> ast::crate_num {
    let metas = metas_with_ident(/*bad*/copy *e.intr.get(ident), metas);

    match existing_match(e, metas, hash) {
      None => {
        let load_ctxt: loader::ctxt = {
            diag: e.diag,
            filesearch: e.filesearch,
            span: span,
            ident: ident,
            metas: metas,
            hash: hash,
            os: e.os,
            static: e.statik,
            intr: e.intr
        };
        let cinfo = loader::load_library_crate(load_ctxt);

        let cfilename = Path(cinfo.ident);
        let cdata = cinfo.data;

        let attrs = decoder::get_crate_attributes(cdata);
        let linkage_metas = attr::find_linkage_metas(attrs);
        let hash = decoder::get_crate_hash(cdata);

        // Claim this crate number and cache it
        let cnum = e.next_crate_num;
        e.crate_cache.push({cnum: cnum, span: span,
                            hash: hash, metas: @linkage_metas});
        e.next_crate_num += 1;

        // Now resolve the crates referenced by this crate
        let cnum_map = resolve_crate_deps(e, cdata);

        let cname =
            match attr::last_meta_item_value_str_by_name(load_ctxt.metas,
                                                         ~"name") {
              option::Some(ref v) => (/*bad*/copy *v),
              option::None => /*bad*/copy *e.intr.get(ident)
            };
        let cmeta = @{name: cname, data: cdata,
                      cnum_map: cnum_map, cnum: cnum};

        let cstore = e.cstore;
        cstore::set_crate_data(cstore, cnum, cmeta);
        cstore::add_used_crate_file(cstore, &cfilename);
        return cnum;
      }
      Some(cnum) => {
        return cnum;
      }
    }
}

// Go through the crate metadata and load any crates that it references
fn resolve_crate_deps(e: @mut Env, cdata: @~[u8]) -> cstore::cnum_map {
    debug!("resolving deps of external crate");
    // The map from crate numbers in the crate we're resolving to local crate
    // numbers
    let cnum_map = HashMap();
    for decoder::get_crate_deps(e.intr, cdata).each |dep| {
        let extrn_cnum = dep.cnum;
        let cname = dep.name;
        let cmetas = metas_with(/*bad*/copy dep.vers, ~"vers", ~[]);
        debug!("resolving dep crate %s ver: %s hash: %s",
               *e.intr.get(dep.name), dep.vers, dep.hash);
        match existing_match(e, metas_with_ident(copy *e.intr.get(cname),
                                                 copy cmetas),
                             dep.hash) {
          Some(local_cnum) => {
            debug!("already have it");
            // We've already seen this crate
            cnum_map.insert(extrn_cnum, local_cnum);
          }
          None => {
            debug!("need to load it");
            // This is a new one so we've got to load it
            // FIXME (#2404): Need better error reporting than just a bogus
            // span.
            let fake_span = dummy_sp();
            let local_cnum = resolve_crate(e, cname, cmetas,
                                           /*bad*/copy dep.hash, fake_span);
            cnum_map.insert(extrn_cnum, local_cnum);
          }
        }
    }
    return cnum_map;
}

// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<|endoftext|>


<commit_before><commit_msg>Ignore Empty Strings in Word Parsing (#346)<commit_after><|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.

// pp-exact

fn f<T, 'a, 'b) -> int where T : 'a, 'a: 'b, T: Eq {
    0
}
<commit_msg>patch up pretty-printing test<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.

// pp-exact

fn f<'a, 'b, T>(t: T) -> int where T: 'a, 'a:'b, T: Eq { 0 }

fn main() { }

<|endoftext|>


<commit_before><commit_msg>Calculate global maximum<commit_after>extern crate simple_csv;

use std::fs::File;
use std::io::BufReader;
use std::str::FromStr;
use simple_csv::SimpleCsvReader;

fn main(){
    let f = File::open("../long-cadence.csv").unwrap();
    let buf = BufReader::new(f);
    let reader = SimpleCsvReader::new(buf);

    let mut maximum = std::f64::MIN;
    for r in reader {
        let row = r.unwrap();
        maximum = maximum.max(maximum_of(row));
    }

    println!("{}", maximum);
}

fn maximum_of(row: Vec<String>) -> f64 {
    let mut iter = row.iter();
    iter.next(); // dropping time

    let raw: Vec<f64> = iter
        .map(|s| f64::from_str(s).unwrap())
        .collect();
    let maximum = raw
        .iter()
        .fold(std::f64::MIN, |acc, v| acc.max(*v));

    maximum
}
<|endoftext|>


<commit_before><commit_msg>Adds integration test for route53.<commit_after>#![cfg(feature = "route53")]

extern crate rusoto_core;
extern crate rusoto_route53;

use rusoto_route53::{Route53, Route53Client, ListHostedZonesRequest};
use rusoto_core::{DefaultCredentialsProvider, Region, default_tls_client};

#[test]
fn should_list_hosted_zones() {
    let credentials = DefaultCredentialsProvider::new().unwrap();
    let client =
        Route53Client::new(default_tls_client().unwrap(), credentials, Region::UsEast1);
    let request = ListHostedZonesRequest::default();

    client.list_hosted_zones(&request).unwrap();
}
<|endoftext|>


<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 infer::canonical::{Canonical, Canonicalized, CanonicalizedQueryResult, QueryRegionConstraint,
                       QueryResult};
use infer::{InferCtxt, InferOk};
use std::fmt;
use std::rc::Rc;
use traits::query::Fallible;
use traits::ObligationCause;
use ty::fold::TypeFoldable;
use ty::{Lift, ParamEnvAnd, TyCtxt};

pub mod custom;
pub mod eq;
pub mod normalize;
pub mod outlives;
pub mod prove_predicate;
use self::prove_predicate::ProvePredicate;
pub mod subtype;

pub trait TypeOp<'gcx, 'tcx>: Sized + fmt::Debug {
    type Output;

    /// Processes the operation and all resulting obligations,
    /// returning the final result along with any region constraints
    /// (they will be given over to the NLL region solver).
    fn fully_perform(
        self,
        infcx: &InferCtxt<'_, 'gcx, 'tcx>,
    ) -> Fallible<(Self::Output, Option<Rc<Vec<QueryRegionConstraint<'tcx>>>>)>;
}

pub trait QueryTypeOp<'gcx: 'tcx, 'tcx>:
    fmt::Debug + Sized + TypeFoldable<'tcx> + Lift<'gcx>
{
    type QueryResult: TypeFoldable<'tcx> + Lift<'gcx>;

    /// Either converts `self` directly into a `QueryResult` (for
    /// simple cases) or into a `QueryKey` (for more complex cases
    /// where we actually have work to do).
    fn try_fast_path(
        tcx: TyCtxt<'_, 'gcx, 'tcx>,
        key: &ParamEnvAnd<'tcx, Self>,
    ) -> Option<Self::QueryResult>;

    /// Performs the actual query with the canonicalized key -- the
    /// real work happens here. This method is not given an `infcx`
    /// because it shouldn't need one -- and if it had access to one,
    /// it might do things like invoke `sub_regions`, which would be
    /// bad, because it would create subregion relationships that are
    /// not captured in the return value.
    fn perform_query(
        tcx: TyCtxt<'_, 'gcx, 'tcx>,
        canonicalized: Canonicalized<'gcx, ParamEnvAnd<'tcx, Self>>,
    ) -> Fallible<CanonicalizedQueryResult<'gcx, Self::QueryResult>>;

    /// Casts a lifted query result (which is in the gcx lifetime)
    /// into the tcx lifetime. This is always just an identity cast,
    /// but the generic code doesn't realize it -- put another way, in
    /// the generic code, we have a `Lifted<'gcx, Self::QueryResult>`
    /// and we want to convert that to a `Self::QueryResult`. This is
    /// not a priori valid, so we can't do it -- but in practice, it
    /// is always a no-op (e.g., the lifted form of a type,
    /// `Ty<'gcx>`, is a subtype of `Ty<'tcx>`). So we have to push
    /// the operation into the impls that know more specifically what
    /// `QueryResult` is. This operation would (maybe) be nicer with
    /// something like HKTs or GATs, since then we could make
    /// `QueryResult` parametric and `'gcx` and `'tcx` etc.
    fn shrink_to_tcx_lifetime(
        lifted_query_result: &'a CanonicalizedQueryResult<'gcx, Self::QueryResult>,
    ) -> &'a Canonical<'tcx, QueryResult<'tcx, Self::QueryResult>>;

    fn fully_perform_into(
        query_key: ParamEnvAnd<'tcx, Self>,
        infcx: &InferCtxt<'_, 'gcx, 'tcx>,
        output_query_region_constraints: &mut Vec<QueryRegionConstraint<'tcx>>,
    ) -> Fallible<Self::QueryResult> {
        if let Some(result) = QueryTypeOp::try_fast_path(infcx.tcx, &query_key) {
            return Ok(result);
        }

        // FIXME(#33684) -- We need to use
        // `canonicalize_hr_query_hack` here because of things
        // like the subtype query, which go awry around
        // `'static` otherwise.
        let (canonical_self, canonical_var_values) = infcx.canonicalize_hr_query_hack(&query_key);
        let canonical_result = Self::perform_query(infcx.tcx, canonical_self)?;
        let canonical_result = Self::shrink_to_tcx_lifetime(&canonical_result);

        let param_env = query_key.param_env;

        let InferOk { value, obligations } = infcx
            .instantiate_nll_query_result_and_region_obligations(
                &ObligationCause::dummy(),
                param_env,
                &canonical_var_values,
                canonical_result,
                output_query_region_constraints,
            )?;

        // Typically, instantiating NLL query results does not
        // create obligations. However, in some cases there
        // are unresolved type variables, and unify them *can*
        // create obligations. In that case, we have to go
        // fulfill them. We do this via a (recursive) query.
        for obligation in obligations {
            let () = ProvePredicate::fully_perform_into(
                obligation
                    .param_env
                    .and(ProvePredicate::new(obligation.predicate)),
                infcx,
                output_query_region_constraints,
            )?;
        }

        Ok(value)
    }
}

impl<'gcx: 'tcx, 'tcx, Q> TypeOp<'gcx, 'tcx> for ParamEnvAnd<'tcx, Q>
where
    Q: QueryTypeOp<'gcx, 'tcx>,
{
    type Output = Q::QueryResult;

    fn fully_perform(
        self,
        infcx: &InferCtxt<'_, 'gcx, 'tcx>,
    ) -> Fallible<(Self::Output, Option<Rc<Vec<QueryRegionConstraint<'tcx>>>>)> {
        let mut qrc = vec![];
        let r = Q::fully_perform_into(self, infcx, &mut qrc)?;

        // Promote the final query-region-constraints into a
        // (optional) ref-counted vector:
        let opt_qrc = if qrc.is_empty() {
            None
        } else {
            Some(Rc::new(qrc))
        };

        Ok((r, opt_qrc))
    }
}
<commit_msg>update comments<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 infer::canonical::{Canonical, Canonicalized, CanonicalizedQueryResult, QueryRegionConstraint,
                       QueryResult};
use infer::{InferCtxt, InferOk};
use std::fmt;
use std::rc::Rc;
use traits::query::Fallible;
use traits::ObligationCause;
use ty::fold::TypeFoldable;
use ty::{Lift, ParamEnvAnd, TyCtxt};

pub mod custom;
pub mod eq;
pub mod normalize;
pub mod outlives;
pub mod prove_predicate;
use self::prove_predicate::ProvePredicate;
pub mod subtype;

/// "Type ops" are used in NLL to perform some particular action and
/// extract out the resulting region constraints (or an error if it
/// cannot be completed).
pub trait TypeOp<'gcx, 'tcx>: Sized + fmt::Debug {
    type Output;

    /// Processes the operation and all resulting obligations,
    /// returning the final result along with any region constraints
    /// (they will be given over to the NLL region solver).
    fn fully_perform(
        self,
        infcx: &InferCtxt<'_, 'gcx, 'tcx>,
    ) -> Fallible<(Self::Output, Option<Rc<Vec<QueryRegionConstraint<'tcx>>>>)>;
}

/// "Query type ops" are type ops that are implemented using a
/// [canonical query][c]. The `Self` type here contains the kernel of
/// information needed to do the operation -- `TypeOp` is actually
/// implemented for `ParamEnvAnd<Self>`, since we always need to bring
/// along a parameter environment as well. For query type-ops, we will
/// first canonicalize the key and then invoke the query on the tcx,
/// which produces the resulting query region constraints.
///
/// [c]: https://rust-lang-nursery.github.io/rustc-guide/traits/canonicalization.html
pub trait QueryTypeOp<'gcx: 'tcx, 'tcx>:
    fmt::Debug + Sized + TypeFoldable<'tcx> + Lift<'gcx>
{
    type QueryResult: TypeFoldable<'tcx> + Lift<'gcx>;

    /// Give query the option for a simple fast path that never
    /// actually hits the tcx cache lookup etc. Return `Some(r)` with
    /// a final result or `None` to do the full path.
    fn try_fast_path(
        tcx: TyCtxt<'_, 'gcx, 'tcx>,
        key: &ParamEnvAnd<'tcx, Self>,
    ) -> Option<Self::QueryResult>;

    /// Performs the actual query with the canonicalized key -- the
    /// real work happens here. This method is not given an `infcx`
    /// because it shouldn't need one -- and if it had access to one,
    /// it might do things like invoke `sub_regions`, which would be
    /// bad, because it would create subregion relationships that are
    /// not captured in the return value.
    fn perform_query(
        tcx: TyCtxt<'_, 'gcx, 'tcx>,
        canonicalized: Canonicalized<'gcx, ParamEnvAnd<'tcx, Self>>,
    ) -> Fallible<CanonicalizedQueryResult<'gcx, Self::QueryResult>>;

    /// Casts a lifted query result (which is in the gcx lifetime)
    /// into the tcx lifetime. This is always just an identity cast,
    /// but the generic code doesn't realize it -- put another way, in
    /// the generic code, we have a `Lifted<'gcx, Self::QueryResult>`
    /// and we want to convert that to a `Self::QueryResult`. This is
    /// not a priori valid, so we can't do it -- but in practice, it
    /// is always a no-op (e.g., the lifted form of a type,
    /// `Ty<'gcx>`, is a subtype of `Ty<'tcx>`). So we have to push
    /// the operation into the impls that know more specifically what
    /// `QueryResult` is. This operation would (maybe) be nicer with
    /// something like HKTs or GATs, since then we could make
    /// `QueryResult` parametric and `'gcx` and `'tcx` etc.
    fn shrink_to_tcx_lifetime(
        lifted_query_result: &'a CanonicalizedQueryResult<'gcx, Self::QueryResult>,
    ) -> &'a Canonical<'tcx, QueryResult<'tcx, Self::QueryResult>>;

    fn fully_perform_into(
        query_key: ParamEnvAnd<'tcx, Self>,
        infcx: &InferCtxt<'_, 'gcx, 'tcx>,
        output_query_region_constraints: &mut Vec<QueryRegionConstraint<'tcx>>,
    ) -> Fallible<Self::QueryResult> {
        if let Some(result) = QueryTypeOp::try_fast_path(infcx.tcx, &query_key) {
            return Ok(result);
        }

        // FIXME(#33684) -- We need to use
        // `canonicalize_hr_query_hack` here because of things
        // like the subtype query, which go awry around
        // `'static` otherwise.
        let (canonical_self, canonical_var_values) = infcx.canonicalize_hr_query_hack(&query_key);
        let canonical_result = Self::perform_query(infcx.tcx, canonical_self)?;
        let canonical_result = Self::shrink_to_tcx_lifetime(&canonical_result);

        let param_env = query_key.param_env;

        let InferOk { value, obligations } = infcx
            .instantiate_nll_query_result_and_region_obligations(
                &ObligationCause::dummy(),
                param_env,
                &canonical_var_values,
                canonical_result,
                output_query_region_constraints,
            )?;

        // Typically, instantiating NLL query results does not
        // create obligations. However, in some cases there
        // are unresolved type variables, and unify them *can*
        // create obligations. In that case, we have to go
        // fulfill them. We do this via a (recursive) query.
        for obligation in obligations {
            let () = ProvePredicate::fully_perform_into(
                obligation
                    .param_env
                    .and(ProvePredicate::new(obligation.predicate)),
                infcx,
                output_query_region_constraints,
            )?;
        }

        Ok(value)
    }
}

impl<'gcx: 'tcx, 'tcx, Q> TypeOp<'gcx, 'tcx> for ParamEnvAnd<'tcx, Q>
where
    Q: QueryTypeOp<'gcx, 'tcx>,
{
    type Output = Q::QueryResult;

    fn fully_perform(
        self,
        infcx: &InferCtxt<'_, 'gcx, 'tcx>,
    ) -> Fallible<(Self::Output, Option<Rc<Vec<QueryRegionConstraint<'tcx>>>>)> {
        let mut qrc = vec![];
        let r = Q::fully_perform_into(self, infcx, &mut qrc)?;

        // Promote the final query-region-constraints into a
        // (optional) ref-counted vector:
        let opt_qrc = if qrc.is_empty() {
            None
        } else {
            Some(Rc::new(qrc))
        };

        Ok((r, opt_qrc))
    }
}
<|endoftext|>


<commit_before><commit_msg>Create a algebraic datatype code sample<commit_after>enum Tree {
    Empty,
    Leaf(i32),
    Node(Box<Tree>, Box<Tree>)
}

impl std::fmt::Display for Tree {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match *self {
            Tree::Empty => write!(f, "()"),
            Tree::Leaf(x) => write!(f, "({})", x),
            Tree::Node(ref left, ref right) => write!(f, "({} {})", *left, *right)
        }
    }
}

fn max(x: i32, y: i32) -> i32 {
    if x < y { y } else { x }
}

fn depth(tree: &Tree) -> i32 {
    match *tree {
        Tree::Empty   => 0,
        Tree::Leaf(_) => 1,
        Tree::Node(ref left, ref right) => max(depth(&(*left)), depth(&(*right))) + 1
    }
}

fn main() {
    let tree: Tree = Tree::Node(Box::new(Tree::Empty), Box::new(Tree::Leaf(42)));

    println!("tree {} has depth {}", tree, depth(&tree));
}
<|endoftext|>


<commit_before><commit_msg>Allow reconfiguring how often we flush to disk.<commit_after><|endoftext|>


<commit_before><commit_msg>Implemented graphics::points()<commit_after><|endoftext|>


<commit_before><commit_msg>rename protocol to signature to be in line with microsoft spec and set the flags to 0<commit_after><|endoftext|>


<commit_before>use core::clone::Clone;

use alloc::boxed::*;

use common::memory::*;
use common::string::*;
use common::url::*;

use filesystems::unfs::*;

use programs::session::*;

pub struct HTTPScheme;

impl HTTPScheme {
    pub fn encode(text: String) -> String{
        let mut html = String::new();

        for c in text.chars() {
            match c {
                '&' => html = html + "&",
                '"' => html = html + """,
                '<' => html = html + "<",
                '>' => html = html + ">",
                _ => html = html + c
            }
        }

        return html;
    }
}

impl SessionModule for HTTPScheme {
    fn scheme(&self) -> String {
        return "http".to_string();
    }

    fn on_url(&mut self, session: &Session, url: &URL, callback: Box<FnBox(String)>){
        let mut path = String::new();

        for part in url.path.iter() {
            path = path + "/" + part.clone();
        }

        let mut html = "HTTP/1.1 200 OK\r\n".to_string()
                    + "Content-Type: text/html\r\n"
                    + "Connection: keep-alive\r\n"
                    + "\r\n";

        if path == "/files".to_string() {
            html = html + "<title>Files - Redox</title>\n";
        }else if path == "/readme".to_string() {
            html = html + "<title>Readme - Redox</title>\n";
        }else{
            html = html + "<title>Home - Redox</title>\n";
        }
        html = html + "<link rel='icon' href='data:;base64,iVBORw0KGgo='>\n";
        html = html + "<link rel='stylesheet' href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css'>\n";
        html = html + "<link rel='stylesheet' href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap-theme.min.css'>\n";
        html = html + "\n";

        html = html + "
\n";
            html = html + "\n";
            html = html + "
\n";
            html = html + "
\n";
            html = html + "      <button type='button' class='navbar-toggle collapsed' data-toggle='collapse' data-target='#navbar-collapse'></button>\n";
            html = html + "      Redox Web Interface\n";
            html = html + "
\n";
            html = html + "
\n";
            html = html + "
\n";

            if path == "/readme".to_string() {
                html = html + "
Home
\n";
                html = html + "
Readme
\n";
            }else{
                html = html + "
Home
\n";
                html = html + "
Readme
\n";
            }

            html = html + "
\n";
            html = html + "
\n";
            html = html + "
\n";
            html = html + "\n";

            if path == "/readme".to_string() {
                unsafe {
                    html = html + "
\n";
                        let unfs = UnFS::new();
                        let readme_file = "README.md".to_string();
                        let readme_c_str = unfs.load(readme_file.clone());
                        if readme_c_str > 0 {
                            let readme = String::from_c_str(readme_c_str as *const u8);
                            unalloc(readme_c_str);

                            html = html + "
\n";
                                html = html + "
 " + readme_file.clone() + "
";
                            html = html + "
\n";

                            html = html + "
\n";
                                let mut in_code = false;
                                for line in readme.split("\n".to_string()){
                                    if line.starts_with("# ".to_string()){
                                        html = html + "
" + HTTPScheme::encode(line.substr(2, line.len() - 2)) + "
\n";
                                    }else if line.starts_with("## ".to_string()){
                                        html = html + "
" + HTTPScheme::encode(line.substr(3, line.len() - 3)) + "
\n";
                                    }else if line.starts_with("### ".to_string()){
                                        html = html + "
" + HTTPScheme::encode(line.substr(4, line.len() - 4)) + "
\n";
                                    }else if line.starts_with("- ".to_string()){
                                        html = html + "
" + HTTPScheme::encode(line.substr(2, line.len() - 2)) + "
\n";
                                    }else if line.starts_with("```".to_string()){
                                        if in_code {
                                            html = html + "</pre>\n";
                                            in_code = false;
                                        }else{
                                            html = html + "<pre>\n";
                                            in_code = true;
                                        }
                                    }else{
                                        html = html + HTTPScheme::encode(line);
                                        if in_code {
                                            html = html + "\n";
                                        }else{
                                            html = html + "<br/>\n";
                                        }
                                    }
                                }
                                if in_code {
                                    html = html + "</pre>\n";
                                }
                            html = html + "</div>\n";
                        }else{
                            html = html + "<div class='panel-heading'>\n";
                                html = html + "<h3 class='panel-title'><span class='glyphicon glyphicon-exlamation-sign'></span> Failed to open " + readme_file.clone() + "</h3>\n";
                            html = html + "</div>\n";
                        }
                    html = html + "</div>\n";
                }
            }else{
                let url_string = path.substr(1, path.len());
                if url_string.len() > 0 {
                    let url = URL::from_string(url_string);
                    let data = String::new(); //session.on_url(&url);
                    html = html + "<table class='table table-bordered'>\n";
                        html = html + "  <caption><h3>" + HTTPScheme::encode(url.to_string()) + "</h3></caption>\n";
                        for line in data.split("\n".to_string()) {
                            html = html + "<tr><td>" + HTTPScheme::encode(line.clone()) + "</td></tr>\n";
                        }
                    html = html + "</table>\n";
                }else{
                    html = html + "<table class='table table-bordered'>\n";
                        html = html + "  <caption><h3>Schemes</h3></caption>\n";
                        for module in session.modules.iter() {
                            let scheme = module.scheme();
                            if scheme.len() > 0 {
                                html = html + "<tr><td><a href='/" + scheme.clone() + ":///'>" + scheme.clone() + "</a></td></tr>";
                            }
                        }
                    html = html + "</table>\n";
                }
            }
        html = html + "</div>\n";

        callback(html);
    }
}
<commit_msg>Callbacks for access to session urls<commit_after>use core::clone::Clone;

use alloc::boxed::*;

use common::memory::*;
use common::string::*;
use common::url::*;

use programs::session::*;

pub struct HTTPScheme;

impl HTTPScheme {
    pub fn encode(text: String) -> String{
        let mut html = String::new();

        for c in text.chars() {
            match c {
                '&' => html = html + "&",
                '"' => html = html + """,
                '<' => html = html + "<",
                '>' => html = html + ">",
                _ => html = html + c
            }
        }

        return html;
    }
}

impl SessionModule for HTTPScheme {
    fn scheme(&self) -> String {
        return "http".to_string();
    }

    fn on_url(&mut self, session: &Session, url: &URL, callback: Box<FnBox(String)>){
        let mut path = String::new();

        for part in url.path.iter() {
            path = path + "/" + part.clone();
        }

        let html_path = path.clone();
        let html_callback: Box<FnBox(String)> = box move |content|{
            let mut html = "HTTP/1.1 200 OK\r\n".to_string()
                        + "Content-Type: text/html\r\n"
                        + "Connection: keep-alive\r\n"
                        + "\r\n";

            if html_path == "/readme".to_string() {
                html = html + "<title>Readme - Redox</title>\n";
            }else{
                html = html + "<title>Home - Redox</title>\n";
            }
            html = html + "<link rel='icon' href='data:;base64,iVBORw0KGgo='>\n";
            html = html + "<link rel='stylesheet' href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css'>\n";
            html = html + "<link rel='stylesheet' href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap-theme.min.css'>\n";
            html = html + "<script src='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js'></script>\n";

            html = html + "<div class='container'>\n";
                html = html + "<nav class='navbar navbar-default'>\n";
                html = html + "  <div class='container-fluid'>\n";
                html = html + "    <div class='navbar-header'>\n";
                html = html + "      <button type='button' class='navbar-toggle collapsed' data-toggle='collapse' data-target='#navbar-collapse'></button>\n";
                html = html + "      <a class='navbar-brand' href='/'>Redox Web Interface</a>\n";
                html = html + "    </div>\n";
                html = html + "    <div class='collapse navbar-collapse' id='navbar-collapse'>\n";
                html = html + "      <ul class='nav navbar-nav navbar-right'>\n";

                if html_path == "/readme".to_string() {
                    html = html + "        <li><a href='/'>Home</a></li>\n";
                    html = html + "        <li class='active'><a href='/readme'>Readme</a></li>\n";
                }else{
                    html = html + "        <li class='active'><a href='/'>Home</a></li>\n";
                    html = html + "        <li><a href='/readme'>Readme</a></li>\n";
                }

                html = html + "      </ul>\n";
                html = html + "    </div>\n";
                html = html + "  </div>\n";
                html = html + "</nav>\n";

                html = html + content;
            html = html + "</div>\n";
            callback(html);
        };

        if path == "/readme".to_string() {
            session.on_url_wrapped(&URL::from_string("file:///README.md".to_string()), box move |response: String|{
                let mut html = "<div class='panel panel-default'>\n".to_string();
                    if response.data as usize > 0 {
                        let readme;
                        unsafe{
                            readme = String::from_c_str(response.data as *const u8);
                        }

                        html = html + "<div class='panel-heading'>\n";
                            html = html + "<h3 class='panel-title'><span class='glyphicon glyphicon-book'></span> README</h3>";
                        html = html + "</div>\n";

                        html = html + "<div class='panel-body'>\n";
                            let mut in_code = false;
                            for line in readme.split("\n".to_string()){
                                if line.starts_with("# ".to_string()){
                                    html = html + "<h1>" + HTTPScheme::encode(line.substr(2, line.len() - 2)) + "</h1>\n";
                                }else if line.starts_with("## ".to_string()){
                                    html = html + "<h2>" + HTTPScheme::encode(line.substr(3, line.len() - 3)) + "</h2>\n";
                                }else if line.starts_with("### ".to_string()){
                                    html = html + "<h3>" + HTTPScheme::encode(line.substr(4, line.len() - 4)) + "</h3>\n";
                                }else if line.starts_with("- ".to_string()){
                                    html = html + "<li>" + HTTPScheme::encode(line.substr(2, line.len() - 2)) + "</li>\n";
                                }else if line.starts_with("```".to_string()){
                                    if in_code {
                                        html = html + "
\n";
                                        in_code = false;
                                    }else{
                                        html = html + "
\n";
                                        in_code = true;
                                    }
                                }else{
                                    html = html + HTTPScheme::encode(line);
                                    if in_code {
                                        html = html + "\n";
                                    }else{
                                        html = html + "
\n";
                                    }
                                }
                            }
                            if in_code {
                                html = html + "
\n";
                            }
                        html = html + "
\n";
                    }else{
                        html = html + "
\n";
                            html = html + "
 Failed to open README
\n";
                        html = html + "
\n";
                    }
                html = html + "
\n";

                html_callback(html);
            });
        }else{
            let url_string = path.substr(1, path.len());
            if url_string.len() > 0 {
                let url_string_copy = url_string.clone();
                session.on_url_wrapped(&URL::from_string(url_string), box move |response: String|{
                    let mut html = "
\n".to_string();
                        html = html + "

" + HTTPScheme::encode(url_string_copy) + "

\n";
                        for line in response.split("\n".to_string()) {
                            html = html + "
" + HTTPScheme::encode(line.clone()) + "
\n";
                        }
                    html = html + "
\n";
                    html_callback(html);
                });
            }else{
                let mut html = "
\n".to_string();
                    html = html + "

Schemes

\n";
                    for module in session.modules.iter() {
                        let scheme = module.scheme();
                        if scheme.len() > 0 {
                            html = html + "
" + scheme.clone() + "
";
                        }
                    }
                html = html + "
\n";
                html_callback(html);
            }
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>:hammer: Fix typo<commit_after><|endoftext|>


<commit_before><commit_msg>playing with rust<commit_after><|endoftext|>


<commit_before><commit_msg>Glue in location ingest.<commit_after><|endoftext|>


<commit_before><commit_msg>Prevent calling waitpid with dead child<commit_after><|endoftext|>


<commit_before><commit_msg>rollup merge of #21066: japaric/issue-20575<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.

// Test that overloaded calls work with zero arity closures

#![feature(box_syntax)]

fn main() {
    let functions: [Box<Fn() -> Option<()>>; 1] = [box || None];

    let _: Option<Vec<()>> = functions.iter().map(|f| (*f)()).collect();
}
<|endoftext|>


<commit_before><commit_msg>add regression test<commit_after>// run-pass
// compile-flags:-Zmir-opt-level=2
pub fn main() {
    let _x: fn() = handle_debug_column;
}

fn handle_debug_column() {
    let sampler = sample_columns();

    let foo = || {
        sampler.get(17);
    };
    foo();
}

fn sample_columns() -> impl Sampler {
    ColumnGen {}
}

struct ColumnGen {}

trait Sampler {
    fn get(&self, index: i32);
}

impl Sampler for ColumnGen {
    fn get(&self, _index: i32) {}
}
<|endoftext|>


<commit_before><commit_msg>Clarify that these are about timetables.<commit_after><|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.

use core::option::{Option, Some, None};
use core::vec;
use lib::llvm::{ValueRef, TypeRef};
use middle::trans::_match;
use middle::trans::build::*;
use middle::trans::common::*;
use middle::trans::machine;
use middle::trans::type_of;
use middle::ty;
use syntax::ast;
use util::ppaux::ty_to_str;

// XXX: should this be done with boxed traits instead of ML-style?
pub enum Repr {
    CEnum,
    Univariant(Struct, Destructor),
    General(~[Struct])
}

enum Destructor {
    DtorPresent,
    DtorAbsent,
    NoDtor
}

struct Struct {
    size: u64,
    align: u64,
    fields: ~[ty::t]
}

pub fn represent_node(bcx: block, node: ast::node_id)
    -> Repr {
    represent_type(bcx.ccx(), node_id_type(bcx, node))
}

pub fn represent_type(cx: @CrateContext, t: ty::t) -> Repr {
    debug!("Representing: %s", ty_to_str(cx.tcx, t));
    // XXX: cache this
    match ty::get(t).sty {
        ty::ty_tup(ref elems) => {
            Univariant(mk_struct(cx, *elems), NoDtor)
        }
        ty::ty_rec(ref fields) => {
            // XXX: Are these in the right order?
            Univariant(mk_struct(cx, fields.map(|f| f.mt.ty)), DtorAbsent)
        }
        ty::ty_struct(def_id, ref substs) => {
            let fields = ty::lookup_struct_fields(cx.tcx, def_id);
            let dt = ty::ty_dtor(cx.tcx, def_id).is_present();
            Univariant(mk_struct(cx, fields.map(|field| {
                ty::lookup_field_type(cx.tcx, def_id, field.id, substs)
            })), if dt { DtorPresent } else { DtorAbsent })
        }
        ty::ty_enum(def_id, ref substs) => {
            struct Case { discr: i64, tys: ~[ty::t] };

            let cases = do ty::enum_variants(cx.tcx, def_id).map |vi| {
                let arg_tys = do vi.args.map |&raw_ty| {
                    ty::subst(cx.tcx, substs, raw_ty)
                };
                Case { discr: vi.disr_val /*bad*/as i64, tys: arg_tys }
            };
            if cases.len() == 0 {
                // Uninhabitable; represent as unit
                Univariant(mk_struct(cx, ~[]), NoDtor)
            } else if cases.len() == 1 && cases[0].discr == 0 {
                // struct, tuple, newtype, etc.
                Univariant(mk_struct(cx, cases[0].tys), NoDtor)
            } else if cases.all(|c| c.tys.len() == 0) {
                CEnum
            } else {
                if !cases.alli(|i,c| c.discr == (i as i64)) {
                    cx.sess.bug(fmt!("non-C-like enum %s with specified \
                                      discriminants",
                                     ty::item_path_str(cx.tcx, def_id)))
                }
                General(cases.map(|c| mk_struct(cx, c.tys)))
            }
        }
        _ => cx.sess.bug(~"adt::represent_type called on non-ADT type")
    }
}

fn mk_struct(cx: @CrateContext, tys: &[ty::t]) -> Struct {
    let lltys = tys.map(|&ty| type_of::sizing_type_of(cx, ty));
    let llty_rec = T_struct(lltys);
    Struct {
        size: machine::llsize_of_alloc(cx, llty_rec) /*bad*/as u64,
        align: machine::llalign_of_min(cx, llty_rec) /*bad*/as u64,
        fields: vec::from_slice(tys)
    }
}

pub fn sizing_fields_of(cx: @CrateContext, r: &Repr) -> ~[TypeRef] {
    generic_fields_of(cx, r, true)
}
pub fn fields_of(cx: @CrateContext, r: &Repr) -> ~[TypeRef] {
    generic_fields_of(cx, r, false)
}
fn generic_fields_of(cx: @CrateContext, r: &Repr, sizing: bool)
    -> ~[TypeRef] {
    match *r {
        CEnum => ~[T_enum_discrim(cx)],
        Univariant(ref st, dt) => {
            let f = if sizing {
                st.fields.map(|&ty| type_of::sizing_type_of(cx, ty))
            } else {
                st.fields.map(|&ty| type_of::type_of(cx, ty))
            };
            match dt {
                NoDtor => f,
                DtorAbsent => ~[T_struct(f)],
                DtorPresent => ~[T_struct(f), T_i8()]
            }
        }
        General(ref sts) => {
            ~[T_enum_discrim(cx),
              T_array(T_i8(), sts.map(|st| st.size).max() /*bad*/as uint)]
        }
    }
}

pub fn trans_switch(bcx: block, r: &Repr, scrutinee: ValueRef) ->
    (_match::branch_kind, Option<ValueRef>) {
    // XXX: LoadRangeAssert
    match *r {
        CEnum => {
            (_match::switch, Some(Load(bcx, GEPi(bcx, scrutinee, [0, 0]))))
        }
        Univariant(*) => {
            (_match::single, None)
        }
        General(*) => {
            (_match::switch, Some(Load(bcx, GEPi(bcx, scrutinee, [0, 0]))))
        }
    }
}

pub fn trans_case(bcx: block, r: &Repr, discr: int) -> _match::opt_result {
    match *r {
        CEnum => {
            _match::single_result(rslt(bcx, C_int(bcx.ccx(), discr)))
        }
        Univariant(*) => {
            bcx.ccx().sess.bug(~"no cases for univariants or structs")
        }
        General(*) => {
            _match::single_result(rslt(bcx, C_int(bcx.ccx(), discr)))
        }
    }
}

pub fn trans_set_discr(bcx: block, r: &Repr, val: ValueRef, discr: int) {
    match *r {
        CEnum => {
            Store(bcx, C_int(bcx.ccx(), discr), GEPi(bcx, val, [0, 0]))
        }
        Univariant(_, DtorPresent) => {
            assert discr == 0;
            Store(bcx, C_u8(1), GEPi(bcx, val, [0, 1]))
        }
        Univariant(*) => {
            assert discr == 0;
        }
        General(*) => {
            Store(bcx, C_int(bcx.ccx(), discr), GEPi(bcx, val, [0, 0]))
        }
    }
}

pub fn num_args(r: &Repr, discr: int) -> uint {
    match *r {
        CEnum => 0,
        Univariant(ref st, _dt) => { assert discr == 0; st.fields.len() }
        General(ref cases) => cases[discr as uint].fields.len()
    }
}

pub fn trans_GEP(bcx: block, r: &Repr, val: ValueRef, discr: int, ix: uint)
    -> ValueRef {
    // Note: if this ever needs to generate conditionals (e.g., if we
    // decide to do some kind of cdr-coding-like non-unique repr
    // someday), it'll need to return a possibly-new bcx as well.
    match *r {
        CEnum => {
            bcx.ccx().sess.bug(~"element access in C-like enum")
        }
        Univariant(ref st, dt) => {
            assert discr == 0;
            let val = match dt {
                NoDtor => val,
                DtorPresent | DtorAbsent => GEPi(bcx, val, [0, 0])
            };
            struct_GEP(bcx, st, val, ix)
        }
        General(ref cases) => {
            struct_GEP(bcx, &cases[discr as uint],
                       GEPi(bcx, val, [0, 1]), ix)
        }
    }
}

fn struct_GEP(bcx: block, st: &Struct, val: ValueRef, ix: uint)
    -> ValueRef {
    let ccx = bcx.ccx();

    let real_llty = T_struct(st.fields.map(
        |&ty| type_of::type_of(ccx, ty)));
    let cast_val = PointerCast(bcx, val, T_ptr(real_llty));

    GEPi(bcx, cast_val, [0, ix])
}

pub fn trans_const(ccx: @CrateContext, r: &Repr, discr: int,
                   vals: &[ValueRef]) -> ValueRef {
    match *r {
        CEnum => {
            assert vals.len() == 0;
            C_int(ccx, discr)
        }
        Univariant(ref st, _dt) => {
            assert discr == 0;
            // consts are never destroyed, so the dtor flag is not needed
            C_struct(build_const_struct(ccx, st, vals))
        }
        General(ref cases) => {
            let case = &cases[discr as uint];
            let max_sz = cases.map(|s| s.size).max();
            let body = build_const_struct(ccx, case, vals);

            C_struct([C_int(ccx, discr),
                      C_packed_struct([C_struct(body)]),
                      padding(max_sz - case.size)])
        }
    }
}

fn padding(size: u64) -> ValueRef {
    C_undef(T_array(T_i8(), size /*bad*/as uint))
}

fn build_const_struct(ccx: @CrateContext, st: &Struct, vals: &[ValueRef])
    -> ~[ValueRef] {
    assert vals.len() == st.fields.len();

    let mut offset = 0;
    let mut cfields = ~[];
    for st.fields.eachi |i, &ty| {
        let llty = type_of::sizing_type_of(ccx, ty);
        let type_align = machine::llalign_of_min(ccx, llty)
            /*bad*/as u64;
        let val_align = machine::llalign_of_min(ccx, val_ty(vals[i]))
            /*bad*/as u64;
        let target_offset = roundup(offset, type_align);
        offset = roundup(offset, val_align);
        if (offset != target_offset) {
            cfields.push(padding(target_offset - offset));
            offset = target_offset;
        }
        assert !is_undef(vals[i]);
        // If that assert fails, could change it to wrap in a struct?
        cfields.push(vals[i]);
    }

    return cfields;
}

#[always_inline]
fn roundup(x: u64, a: u64) -> u64 { ((x + (a - 1)) / a) * a }

pub fn const_get_discrim(ccx: @CrateContext, r: &Repr, val: ValueRef)
    -> int {
    match *r {
        CEnum(*) => const_to_int(val) as int,
        Univariant(*) => 0,
        General(*) => const_to_int(const_get_elt(ccx, val, [0])) as int,
    }
}

pub fn const_get_element(ccx: @CrateContext, r: &Repr, val: ValueRef,
                         _discr: int, ix: uint) -> ValueRef {
    // Not to be confused with common::const_get_elt.
    match *r {
        CEnum(*) => ccx.sess.bug(~"element access in C-like enum const"),
        Univariant(*) => const_struct_field(ccx, val, ix),
        General(*) => const_struct_field(ccx, const_get_elt(ccx, val,
                                                            [1, 0]), ix)
    }
}

fn const_struct_field(ccx: @CrateContext, val: ValueRef, ix: uint)
    -> ValueRef {
    // Get the ix-th non-undef element of the struct.
    let mut real_ix = 0; // actual position in the struct
    let mut ix = ix; // logical index relative to real_ix
    let mut field;
    loop {
        loop {
            field = const_get_elt(ccx, val, [real_ix]);
            if !is_undef(field) {
                break;
            }
            real_ix = real_ix + 1;
        }
        if ix == 0 {
            return field;
        }
        ix = ix - 1;
        real_ix = real_ix + 1;
    }
}
<commit_msg>Avoid unnecessary casts in struct_GEP<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.

use core::option::{Option, Some, None};
use core::vec;
use lib::llvm::{ValueRef, TypeRef};
use middle::trans::_match;
use middle::trans::build::*;
use middle::trans::common::*;
use middle::trans::machine;
use middle::trans::type_of;
use middle::ty;
use syntax::ast;
use util::ppaux::ty_to_str;

// XXX: should this be done with boxed traits instead of ML-style?
pub enum Repr {
    CEnum,
    Univariant(Struct, Destructor),
    General(~[Struct])
}

enum Destructor {
    DtorPresent,
    DtorAbsent,
    NoDtor
}

struct Struct {
    size: u64,
    align: u64,
    fields: ~[ty::t]
}

pub fn represent_node(bcx: block, node: ast::node_id)
    -> Repr {
    represent_type(bcx.ccx(), node_id_type(bcx, node))
}

pub fn represent_type(cx: @CrateContext, t: ty::t) -> Repr {
    debug!("Representing: %s", ty_to_str(cx.tcx, t));
    // XXX: cache this
    match ty::get(t).sty {
        ty::ty_tup(ref elems) => {
            Univariant(mk_struct(cx, *elems), NoDtor)
        }
        ty::ty_rec(ref fields) => {
            // XXX: Are these in the right order?
            Univariant(mk_struct(cx, fields.map(|f| f.mt.ty)), DtorAbsent)
        }
        ty::ty_struct(def_id, ref substs) => {
            let fields = ty::lookup_struct_fields(cx.tcx, def_id);
            let dt = ty::ty_dtor(cx.tcx, def_id).is_present();
            Univariant(mk_struct(cx, fields.map(|field| {
                ty::lookup_field_type(cx.tcx, def_id, field.id, substs)
            })), if dt { DtorPresent } else { DtorAbsent })
        }
        ty::ty_enum(def_id, ref substs) => {
            struct Case { discr: i64, tys: ~[ty::t] };

            let cases = do ty::enum_variants(cx.tcx, def_id).map |vi| {
                let arg_tys = do vi.args.map |&raw_ty| {
                    ty::subst(cx.tcx, substs, raw_ty)
                };
                Case { discr: vi.disr_val /*bad*/as i64, tys: arg_tys }
            };
            if cases.len() == 0 {
                // Uninhabitable; represent as unit
                Univariant(mk_struct(cx, ~[]), NoDtor)
            } else if cases.len() == 1 && cases[0].discr == 0 {
                // struct, tuple, newtype, etc.
                Univariant(mk_struct(cx, cases[0].tys), NoDtor)
            } else if cases.all(|c| c.tys.len() == 0) {
                CEnum
            } else {
                if !cases.alli(|i,c| c.discr == (i as i64)) {
                    cx.sess.bug(fmt!("non-C-like enum %s with specified \
                                      discriminants",
                                     ty::item_path_str(cx.tcx, def_id)))
                }
                General(cases.map(|c| mk_struct(cx, c.tys)))
            }
        }
        _ => cx.sess.bug(~"adt::represent_type called on non-ADT type")
    }
}

fn mk_struct(cx: @CrateContext, tys: &[ty::t]) -> Struct {
    let lltys = tys.map(|&ty| type_of::sizing_type_of(cx, ty));
    let llty_rec = T_struct(lltys);
    Struct {
        size: machine::llsize_of_alloc(cx, llty_rec) /*bad*/as u64,
        align: machine::llalign_of_min(cx, llty_rec) /*bad*/as u64,
        fields: vec::from_slice(tys)
    }
}

pub fn sizing_fields_of(cx: @CrateContext, r: &Repr) -> ~[TypeRef] {
    generic_fields_of(cx, r, true)
}
pub fn fields_of(cx: @CrateContext, r: &Repr) -> ~[TypeRef] {
    generic_fields_of(cx, r, false)
}
fn generic_fields_of(cx: @CrateContext, r: &Repr, sizing: bool)
    -> ~[TypeRef] {
    match *r {
        CEnum => ~[T_enum_discrim(cx)],
        Univariant(ref st, dt) => {
            let f = if sizing {
                st.fields.map(|&ty| type_of::sizing_type_of(cx, ty))
            } else {
                st.fields.map(|&ty| type_of::type_of(cx, ty))
            };
            match dt {
                NoDtor => f,
                DtorAbsent => ~[T_struct(f)],
                DtorPresent => ~[T_struct(f), T_i8()]
            }
        }
        General(ref sts) => {
            ~[T_enum_discrim(cx),
              T_array(T_i8(), sts.map(|st| st.size).max() /*bad*/as uint)]
        }
    }
}

pub fn trans_switch(bcx: block, r: &Repr, scrutinee: ValueRef) ->
    (_match::branch_kind, Option<ValueRef>) {
    // XXX: LoadRangeAssert
    match *r {
        CEnum => {
            (_match::switch, Some(Load(bcx, GEPi(bcx, scrutinee, [0, 0]))))
        }
        Univariant(*) => {
            (_match::single, None)
        }
        General(*) => {
            (_match::switch, Some(Load(bcx, GEPi(bcx, scrutinee, [0, 0]))))
        }
    }
}

pub fn trans_case(bcx: block, r: &Repr, discr: int) -> _match::opt_result {
    match *r {
        CEnum => {
            _match::single_result(rslt(bcx, C_int(bcx.ccx(), discr)))
        }
        Univariant(*) => {
            bcx.ccx().sess.bug(~"no cases for univariants or structs")
        }
        General(*) => {
            _match::single_result(rslt(bcx, C_int(bcx.ccx(), discr)))
        }
    }
}

pub fn trans_set_discr(bcx: block, r: &Repr, val: ValueRef, discr: int) {
    match *r {
        CEnum => {
            Store(bcx, C_int(bcx.ccx(), discr), GEPi(bcx, val, [0, 0]))
        }
        Univariant(_, DtorPresent) => {
            assert discr == 0;
            Store(bcx, C_u8(1), GEPi(bcx, val, [0, 1]))
        }
        Univariant(*) => {
            assert discr == 0;
        }
        General(*) => {
            Store(bcx, C_int(bcx.ccx(), discr), GEPi(bcx, val, [0, 0]))
        }
    }
}

pub fn num_args(r: &Repr, discr: int) -> uint {
    match *r {
        CEnum => 0,
        Univariant(ref st, _dt) => { assert discr == 0; st.fields.len() }
        General(ref cases) => cases[discr as uint].fields.len()
    }
}

pub fn trans_GEP(bcx: block, r: &Repr, val: ValueRef, discr: int, ix: uint)
    -> ValueRef {
    // Note: if this ever needs to generate conditionals (e.g., if we
    // decide to do some kind of cdr-coding-like non-unique repr
    // someday), it'll need to return a possibly-new bcx as well.
    match *r {
        CEnum => {
            bcx.ccx().sess.bug(~"element access in C-like enum")
        }
        Univariant(ref st, dt) => {
            assert discr == 0;
            let val = match dt {
                NoDtor => val,
                DtorPresent | DtorAbsent => GEPi(bcx, val, [0, 0])
            };
            struct_GEP(bcx, st, val, ix, false)
        }
        General(ref cases) => {
            struct_GEP(bcx, &cases[discr as uint],
                       GEPi(bcx, val, [0, 1]), ix, true)
        }
    }
}

fn struct_GEP(bcx: block, st: &Struct, val: ValueRef, ix: uint,
              needs_cast: bool) -> ValueRef {
    let ccx = bcx.ccx();

    let val = if needs_cast {
        let real_llty = T_struct(st.fields.map(
            |&ty| type_of::type_of(ccx, ty)));
        PointerCast(bcx, val, T_ptr(real_llty))
    } else {
        val
    };

    GEPi(bcx, val, [0, ix])
}

pub fn trans_const(ccx: @CrateContext, r: &Repr, discr: int,
                   vals: &[ValueRef]) -> ValueRef {
    match *r {
        CEnum => {
            assert vals.len() == 0;
            C_int(ccx, discr)
        }
        Univariant(ref st, _dt) => {
            assert discr == 0;
            // consts are never destroyed, so the dtor flag is not needed
            C_struct(build_const_struct(ccx, st, vals))
        }
        General(ref cases) => {
            let case = &cases[discr as uint];
            let max_sz = cases.map(|s| s.size).max();
            let body = build_const_struct(ccx, case, vals);

            C_struct([C_int(ccx, discr),
                      C_packed_struct([C_struct(body)]),
                      padding(max_sz - case.size)])
        }
    }
}

fn padding(size: u64) -> ValueRef {
    C_undef(T_array(T_i8(), size /*bad*/as uint))
}

fn build_const_struct(ccx: @CrateContext, st: &Struct, vals: &[ValueRef])
    -> ~[ValueRef] {
    assert vals.len() == st.fields.len();

    let mut offset = 0;
    let mut cfields = ~[];
    for st.fields.eachi |i, &ty| {
        let llty = type_of::sizing_type_of(ccx, ty);
        let type_align = machine::llalign_of_min(ccx, llty)
            /*bad*/as u64;
        let val_align = machine::llalign_of_min(ccx, val_ty(vals[i]))
            /*bad*/as u64;
        let target_offset = roundup(offset, type_align);
        offset = roundup(offset, val_align);
        if (offset != target_offset) {
            cfields.push(padding(target_offset - offset));
            offset = target_offset;
        }
        assert !is_undef(vals[i]);
        // If that assert fails, could change it to wrap in a struct?
        cfields.push(vals[i]);
    }

    return cfields;
}

#[always_inline]
fn roundup(x: u64, a: u64) -> u64 { ((x + (a - 1)) / a) * a }

pub fn const_get_discrim(ccx: @CrateContext, r: &Repr, val: ValueRef)
    -> int {
    match *r {
        CEnum(*) => const_to_int(val) as int,
        Univariant(*) => 0,
        General(*) => const_to_int(const_get_elt(ccx, val, [0])) as int,
    }
}

pub fn const_get_element(ccx: @CrateContext, r: &Repr, val: ValueRef,
                         _discr: int, ix: uint) -> ValueRef {
    // Not to be confused with common::const_get_elt.
    match *r {
        CEnum(*) => ccx.sess.bug(~"element access in C-like enum const"),
        Univariant(*) => const_struct_field(ccx, val, ix),
        General(*) => const_struct_field(ccx, const_get_elt(ccx, val,
                                                            [1, 0]), ix)
    }
}

fn const_struct_field(ccx: @CrateContext, val: ValueRef, ix: uint)
    -> ValueRef {
    // Get the ix-th non-undef element of the struct.
    let mut real_ix = 0; // actual position in the struct
    let mut ix = ix; // logical index relative to real_ix
    let mut field;
    loop {
        loop {
            field = const_get_elt(ccx, val, [real_ix]);
            if !is_undef(field) {
                break;
            }
            real_ix = real_ix + 1;
        }
        if ix == 0 {
            return field;
        }
        ix = ix - 1;
        real_ix = real_ix + 1;
    }
}
<|endoftext|>