Merge branch 'master' into 35123-map3

This commit is contained in:
Mikhail Modin 2016-09-23 06:52:06 +03:00
commit 20c10913ff
757 changed files with 23893 additions and 20370 deletions

View file

@ -269,6 +269,7 @@ class RustBuild:
sys.exit(ret)
def build_triple(self):
default_encoding = sys.getdefaultencoding()
config = self.get_toml('build')
if config:
return config
@ -276,8 +277,8 @@ class RustBuild:
if config:
return config
try:
ostype = subprocess.check_output(['uname', '-s']).strip()
cputype = subprocess.check_output(['uname', '-m']).strip()
ostype = subprocess.check_output(['uname', '-s']).strip().decode(default_encoding)
cputype = subprocess.check_output(['uname', '-m']).strip().decode(default_encoding)
except (subprocess.CalledProcessError, WindowsError):
if sys.platform == 'win32':
return 'x86_64-pc-windows-msvc'
@ -289,7 +290,8 @@ class RustBuild:
# Darwin's `uname -s` lies and always returns i386. We have to use
# sysctl instead.
if ostype == 'Darwin' and cputype == 'i686':
sysctl = subprocess.check_output(['sysctl', 'hw.optional.x86_64'])
args = ['sysctl', 'hw.optional.x86_64']
sysctl = subprocess.check_output(args).decode(default_encoding)
if ': 1' in sysctl:
cputype = 'x86_64'

View file

@ -148,6 +148,9 @@ pub fn compiletest(build: &Build,
if let Some(ref dir) = build.lldb_python_dir {
cmd.arg("--lldb-python-dir").arg(dir);
}
let llvm_config = build.llvm_config(target);
let llvm_version = output(Command::new(&llvm_config).arg("--version"));
cmd.arg("--llvm-version").arg(llvm_version);
cmd.args(&build.flags.args);
@ -158,7 +161,6 @@ pub fn compiletest(build: &Build,
// Only pass correct values for these flags for the `run-make` suite as it
// requires that a C++ compiler was configured which isn't always the case.
if suite == "run-make" {
let llvm_config = build.llvm_config(target);
let llvm_components = output(Command::new(&llvm_config).arg("--components"));
let llvm_cxxflags = output(Command::new(&llvm_config).arg("--cxxflags"));
cmd.arg("--cc").arg(build.cc(target))

View file

@ -28,7 +28,6 @@ pub fn clean(build: &Build) {
let out = build.out.join(host);
rm_rf(build, &out.join("compiler-rt"));
rm_rf(build, &out.join("doc"));
for stage in 0..4 {

View file

@ -16,12 +16,14 @@
//! compiler. This module is also responsible for assembling the sysroot as it
//! goes along from the output of the previous stage.
use std::cmp;
use std::collections::HashMap;
use std::fs;
use std::fs::{self, File};
use std::path::{Path, PathBuf};
use std::process::Command;
use build_helper::output;
use filetime::FileTime;
use util::{exe, staticlib, libdir, mtime, is_dylib, copy};
use {Build, Compiler, Mode};
@ -35,13 +37,23 @@ pub fn std<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
println!("Building stage{} std artifacts ({} -> {})", compiler.stage,
compiler.host, target);
// Move compiler-rt into place as it'll be required by the compiler when
// building the standard library to link the dylib of libstd
let libdir = build.sysroot_libdir(compiler, target);
let _ = fs::remove_dir_all(&libdir);
t!(fs::create_dir_all(&libdir));
copy(&build.compiler_rt_built.borrow()[target],
&libdir.join(staticlib("compiler-rt", target)));
// FIXME(stage0) remove this `if` after the next snapshot
// The stage0 compiler still passes the `-lcompiler-rt` flag to the linker but now `bootstrap`
// never builds a `libcopmiler-rt.a`! We'll fill the hole by simply copying stage0's
// `libcompiler-rt.a` to where the stage1's one is expected (though we could as well just use
// an empty `.a` archive). Note that the symbols of that stage0 `libcompiler-rt.a` won't make
// it to the final binary because now `libcore.rlib` also contains the symbols that
// `libcompiler-rt.a` provides. Since that rlib appears first in the linker arguments, its
// symbols are used instead of `libcompiler-rt.a`'s.
if compiler.stage == 0 {
let rtlib = &staticlib("compiler-rt", target);
let src = build.rustc.parent().unwrap().parent().unwrap().join("lib").join("rustlib")
.join(target).join("lib").join(rtlib);
copy(&src, &libdir.join(rtlib));
}
// Some platforms have startup objects that may be required to produce the
// libstd dynamic library, for example.
@ -59,13 +71,14 @@ pub fn std<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
cargo.env("JEMALLOC_OVERRIDE", jemalloc);
}
}
if let Some(ref p) = build.config.musl_root {
if target.contains("musl") {
if target.contains("musl") {
if let Some(p) = build.musl_root(target) {
cargo.env("MUSL_ROOT", p);
}
}
build.run(&mut cargo);
update_mtime(&libstd_stamp(build, compiler, target));
std_link(build, target, compiler, compiler.host);
}
@ -83,26 +96,24 @@ pub fn std_link(build: &Build,
// If we're linking one compiler host's output into another, then we weren't
// called from the `std` method above. In that case we clean out what's
// already there and then also link compiler-rt into place.
// already there.
if host != compiler.host {
let _ = fs::remove_dir_all(&libdir);
t!(fs::create_dir_all(&libdir));
copy(&build.compiler_rt_built.borrow()[target],
&libdir.join(staticlib("compiler-rt", target)));
}
add_to_sysroot(&out_dir, &libdir);
if target.contains("musl") && !target.contains("mips") {
copy_third_party_objects(build, target, &libdir);
copy_musl_third_party_objects(build, &libdir);
}
}
/// Copies the crt(1,i,n).o startup objects
///
/// Only required for musl targets that statically link to libc
fn copy_third_party_objects(build: &Build, target: &str, into: &Path) {
fn copy_musl_third_party_objects(build: &Build, into: &Path) {
for &obj in &["crt1.o", "crti.o", "crtn.o"] {
copy(&compiler_file(build.cc(target), obj), &into.join(obj));
copy(&build.config.musl_root.as_ref().unwrap().join("lib").join(obj), &into.join(obj));
}
}
@ -117,14 +128,16 @@ fn build_startup_objects(build: &Build, target: &str, into: &Path) {
return
}
let compiler = Compiler::new(0, &build.config.build);
let compiler = build.compiler_path(&compiler);
let compiler_path = build.compiler_path(&compiler);
for file in t!(fs::read_dir(build.src.join("src/rtstartup"))) {
let file = t!(file);
build.run(Command::new(&compiler)
.arg("--emit=obj")
.arg("--out-dir").arg(into)
.arg(file.path()));
let mut cmd = Command::new(&compiler_path);
build.add_bootstrap_key(&compiler, &mut cmd);
build.run(cmd.arg("--target").arg(target)
.arg("--emit=obj")
.arg("--out-dir").arg(into)
.arg(file.path()));
}
for obj in ["crt2.o", "dllcrt2.o"].iter() {
@ -141,11 +154,12 @@ pub fn test<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
println!("Building stage{} test artifacts ({} -> {})", compiler.stage,
compiler.host, target);
let out_dir = build.cargo_out(compiler, Mode::Libtest, target);
build.clear_if_dirty(&out_dir, &libstd_shim(build, compiler, target));
build.clear_if_dirty(&out_dir, &libstd_stamp(build, compiler, target));
let mut cargo = build.cargo(compiler, Mode::Libtest, target, "build");
cargo.arg("--manifest-path")
.arg(build.src.join("src/rustc/test_shim/Cargo.toml"));
build.run(&mut cargo);
update_mtime(&libtest_stamp(build, compiler, target));
test_link(build, target, compiler, compiler.host);
}
@ -173,7 +187,7 @@ pub fn rustc<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
compiler.stage, compiler.host, target);
let out_dir = build.cargo_out(compiler, Mode::Librustc, target);
build.clear_if_dirty(&out_dir, &libtest_shim(build, compiler, target));
build.clear_if_dirty(&out_dir, &libtest_stamp(build, compiler, target));
let mut cargo = build.cargo(compiler, Mode::Librustc, target, "build");
cargo.arg("--features").arg(build.rustc_features())
@ -203,6 +217,10 @@ pub fn rustc<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
cargo.env("LLVM_RUSTLLVM", "1");
}
cargo.env("LLVM_CONFIG", build.llvm_config(target));
let target_config = build.config.target_config.get(target);
if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) {
cargo.env("CFG_LLVM_ROOT", s);
}
if build.config.llvm_static_stdcpp {
cargo.env("LLVM_STATIC_STDCPP",
compiler_file(build.cxx(target), "libstdc++.a"));
@ -234,14 +252,14 @@ pub fn rustc_link(build: &Build,
/// Cargo's output path for the standard library in a given stage, compiled
/// by a particular compiler for the specified target.
fn libstd_shim(build: &Build, compiler: &Compiler, target: &str) -> PathBuf {
build.cargo_out(compiler, Mode::Libstd, target).join("libstd_shim.rlib")
fn libstd_stamp(build: &Build, compiler: &Compiler, target: &str) -> PathBuf {
build.cargo_out(compiler, Mode::Libstd, target).join(".libstd.stamp")
}
/// Cargo's output path for libtest in a given stage, compiled by a particular
/// compiler for the specified target.
fn libtest_shim(build: &Build, compiler: &Compiler, target: &str) -> PathBuf {
build.cargo_out(compiler, Mode::Libtest, target).join("libtest_shim.rlib")
fn libtest_stamp(build: &Build, compiler: &Compiler, target: &str) -> PathBuf {
build.cargo_out(compiler, Mode::Libtest, target).join(".libtest.stamp")
}
fn compiler_file(compiler: &Path, file: &str) -> PathBuf {
@ -354,10 +372,35 @@ pub fn tool(build: &Build, stage: u32, host: &str, tool: &str) {
// Maybe when libstd is compiled it should clear out the rustc of the
// corresponding stage?
// let out_dir = build.cargo_out(stage, &host, Mode::Librustc, target);
// build.clear_if_dirty(&out_dir, &libstd_shim(build, stage, &host, target));
// build.clear_if_dirty(&out_dir, &libstd_stamp(build, stage, &host, target));
let mut cargo = build.cargo(&compiler, Mode::Tool, host, "build");
cargo.arg("--manifest-path")
.arg(build.src.join(format!("src/tools/{}/Cargo.toml", tool)));
build.run(&mut cargo);
}
/// Updates the mtime of a stamp file if necessary, only changing it if it's
/// older than some other file in the same directory.
///
/// We don't know what file Cargo is going to output (because there's a hash in
/// the file name) but we know where it's going to put it. We use this helper to
/// detect changes to that output file by looking at the modification time for
/// all files in a directory and updating the stamp if any are newer.
fn update_mtime(path: &Path) {
let mut max = None;
if let Ok(entries) = path.parent().unwrap().read_dir() {
for entry in entries.map(|e| t!(e)) {
if t!(entry.file_type()).is_file() {
let meta = t!(entry.metadata());
let time = FileTime::from_last_modification_time(&meta);
max = cmp::max(max, Some(time));
}
}
}
if !max.is_none() && max <= Some(mtime(path)) {
return
}
t!(File::create(path));
}

View file

@ -76,9 +76,11 @@ pub struct Config {
// misc
pub channel: String,
// Fallback musl-root for all targets
pub musl_root: Option<PathBuf>,
pub prefix: Option<String>,
pub codegen_tests: bool,
pub nodejs: Option<PathBuf>,
}
/// Per-target configuration stored in the global configuration structure.
@ -89,6 +91,7 @@ pub struct Target {
pub cc: Option<PathBuf>,
pub cxx: Option<PathBuf>,
pub ndk: Option<PathBuf>,
pub musl_root: Option<PathBuf>,
}
/// Structure of the `config.toml` file that configuration is read from.
@ -144,6 +147,7 @@ struct Rust {
rpath: Option<bool>,
optimize_tests: Option<bool>,
debuginfo_tests: Option<bool>,
codegen_tests: Option<bool>,
}
/// TOML representation of how each build target is configured.
@ -232,6 +236,7 @@ impl Config {
set(&mut config.rust_optimize, rust.optimize);
set(&mut config.rust_optimize_tests, rust.optimize_tests);
set(&mut config.rust_debuginfo_tests, rust.debuginfo_tests);
set(&mut config.codegen_tests, rust.codegen_tests);
set(&mut config.rust_rpath, rust.rpath);
set(&mut config.debug_jemalloc, rust.debug_jemalloc);
set(&mut config.use_jemalloc, rust.use_jemalloc);
@ -391,6 +396,9 @@ impl Config {
self.rustc = Some(PathBuf::from(value).join("bin/rustc"));
self.cargo = Some(PathBuf::from(value).join("bin/cargo"));
}
"CFG_NODEJS" if value.len() > 0 => {
self.nodejs = Some(PathBuf::from(value));
}
_ => {}
}
}

View file

@ -1,5 +1,8 @@
# Sample TOML configuration file for building Rust.
#
# To configure rustbuild, copy this file to the directory from which you will be
# running the build, and name it config.toml.
#
# All options are commented out by default in this file, and they're commented
# out with their default values. The build system by default looks for
# `config.toml` in the current directory of a build for build configuration, but
@ -115,10 +118,6 @@
# nightly features
#channel = "dev"
# The root location of the MUSL installation directory. The library directory
# will also need to contain libunwind.a for an unwinding implementation.
#musl-root = "..."
# By default the `rustc` executable is built with `-Wl,-rpath` flags on Unix
# platforms to ensure that the compiler is usable by default from the build
# directory (as it links to a number of dynamic libraries). This may not be
@ -130,6 +129,10 @@
#optimize-tests = true
#debuginfo-tests = true
# Flag indicating whether codegen tests will be run or not. If you get an error
# saying that the FileCheck executable is missing, you may want to disable this.
#codegen-tests = true
# =============================================================================
# Options for specific targets
#
@ -160,3 +163,9 @@
# the NDK for the target lives. This is used to find the C compiler to link and
# build native code.
#android-ndk = "/path/to/ndk"
# The root location of the MUSL installation directory. The library directory
# will also need to contain libunwind.a for an unwinding implementation. Note
# that this option only makes sense for MUSL targets that produce statically
# linked binaries
#musl-root = "..."

View file

@ -388,6 +388,9 @@ pub fn rust_src(build: &Build) {
// Rename directory, so that root folder of tarball has the correct name
t!(fs::rename(&dst_src, &plain_dst_src));
// Create the version file
write_file(&plain_dst_src.join("version"), build.version.as_bytes());
// Create plain source tarball
let mut cmd = Command::new("tar");
cmd.arg("-czf").arg(sanitize_sh(&distdir(build).join(&format!("{}.tar.gz", plain_name))))
@ -431,3 +434,8 @@ fn sanitize_sh(path: &Path) -> String {
Some(format!("/{}/{}", drive, &s[drive.len_utf8() + 2..]))
}
}
fn write_file(path: &Path, data: &[u8]) {
let mut vf = t!(fs::File::create(path));
t!(vf.write_all(data));
}

View file

@ -28,7 +28,6 @@ extern crate rustc_serialize;
extern crate toml;
extern crate regex;
use std::cell::RefCell;
use std::collections::HashMap;
use std::env;
use std::fs::{self, File};
@ -46,7 +45,7 @@ use util::{exe, mtime, libdir, add_lib_path};
/// * The error itself
///
/// This is currently used judiciously throughout the build system rather than
/// using a `Result` with `try!`, but this may change on day...
/// using a `Result` with `try!`, but this may change one day...
macro_rules! t {
($e:expr) => (match $e {
Ok(e) => e,
@ -131,7 +130,6 @@ pub struct Build {
// Runtime state filled in later on
cc: HashMap<String, (gcc::Tool, Option<PathBuf>)>,
cxx: HashMap<String, gcc::Tool>,
compiler_rt_built: RefCell<HashMap<String, PathBuf>>,
}
/// The various "modes" of invoking Cargo.
@ -198,7 +196,6 @@ impl Build {
package_vers: String::new(),
cc: HashMap::new(),
cxx: HashMap::new(),
compiler_rt_built: RefCell::new(HashMap::new()),
gdb_version: None,
lldb_version: None,
lldb_python_dir: None,
@ -252,9 +249,6 @@ impl Build {
Llvm { _dummy } => {
native::llvm(self, target.target);
}
CompilerRt { _dummy } => {
native::compiler_rt(self, target.target);
}
TestHelpers { _dummy } => {
native::test_helpers(self, target.target);
}
@ -585,6 +579,8 @@ impl Build {
if mtime(&stamp) < mtime(input) {
self.verbose(&format!("Dirty - {}", dir.display()));
let _ = fs::remove_dir_all(dir);
} else if stamp.exists() {
return
}
t!(fs::create_dir_all(dir));
t!(File::create(stamp));
@ -839,11 +835,6 @@ impl Build {
}
}
/// Root output directory for compiler-rt compiled for `target`
fn compiler_rt_out(&self, target: &str) -> PathBuf {
self.out.join(target).join("compiler-rt")
}
/// Root output directory for rust_test_helpers library compiled for
/// `target`
fn test_helpers_out(&self, target: &str) -> PathBuf {
@ -977,6 +968,13 @@ impl Build {
}
return base
}
/// Returns the "musl root" for this `target`, if defined
fn musl_root(&self, target: &str) -> Option<&Path> {
self.config.target_config[target].musl_root.as_ref()
.or(self.config.musl_root.as_ref())
.map(|p| &**p)
}
}
impl<'a> Compiler<'a> {

View file

@ -27,7 +27,7 @@ use cmake;
use gcc;
use Build;
use util::{staticlib, up_to_date};
use util::up_to_date;
/// Compile LLVM for `target`.
pub fn llvm(build: &Build, target: &str) {
@ -131,401 +131,6 @@ fn check_llvm_version(build: &Build, llvm_config: &Path) {
panic!("\n\nbad LLVM version: {}, need >=3.5\n\n", version)
}
/// Compiles the `compiler-rt` library, or at least the builtins part of it.
///
/// Note that while compiler-rt has a build system associated with it, we
/// specifically don't use it here. The compiler-rt build system, written in
/// CMake, is actually *very* difficult to work with in terms of getting it to
/// compile on all the relevant platforms we want it to compile on. In the end
/// it became so much pain to work with local patches, work around the oddities
/// of the build system, etc, that we're just building everything by hand now.
///
/// In general compiler-rt is just a bunch of intrinsics that are in practice
/// *very* stable. We just need to make sure that all the relevant functions and
/// such are compiled somewhere and placed in an object file somewhere.
/// Eventually, these should all be written in Rust!
///
/// So below you'll find a listing of every single file in the compiler-rt repo
/// that we're compiling. We just reach in and compile with the `gcc` crate
/// which should have all the relevant flags and such already configured.
///
/// The risk here is that if we update compiler-rt we may need to compile some
/// new intrinsics, but to be honest we surely don't use all of the intrinsics
/// listed below today so the likelihood of us actually needing a new intrinsic
/// is quite low. The failure case is also just that someone reports a link
/// error (if any) and then we just add it to the list. Overall, that cost is
/// far far less than working with compiler-rt's build system over time.
pub fn compiler_rt(build: &Build, target: &str) {
let build_dir = build.compiler_rt_out(target);
let output = build_dir.join(staticlib("compiler-rt", target));
build.compiler_rt_built.borrow_mut().insert(target.to_string(),
output.clone());
t!(fs::create_dir_all(&build_dir));
let mut cfg = gcc::Config::new();
cfg.cargo_metadata(false)
.out_dir(&build_dir)
.target(target)
.host(&build.config.build)
.opt_level(2)
.debug(false);
if target.contains("msvc") {
// Don't pull in extra libraries on MSVC
cfg.flag("/Zl");
// Emulate C99 and C++11's __func__ for MSVC prior to 2013 CTP
cfg.define("__func__", Some("__FUNCTION__"));
} else {
// Turn off various features of gcc and such, mostly copying
// compiler-rt's build system already
cfg.flag("-fno-builtin");
cfg.flag("-fvisibility=hidden");
cfg.flag("-fomit-frame-pointer");
cfg.flag("-ffreestanding");
}
let mut sources = vec![
"absvdi2.c",
"absvsi2.c",
"adddf3.c",
"addsf3.c",
"addvdi3.c",
"addvsi3.c",
"apple_versioning.c",
"ashldi3.c",
"ashrdi3.c",
"clear_cache.c",
"clzdi2.c",
"clzsi2.c",
"cmpdi2.c",
"comparedf2.c",
"comparesf2.c",
"ctzdi2.c",
"ctzsi2.c",
"divdc3.c",
"divdf3.c",
"divdi3.c",
"divmoddi4.c",
"divmodsi4.c",
"divsc3.c",
"divsf3.c",
"divsi3.c",
"divxc3.c",
"extendsfdf2.c",
"extendhfsf2.c",
"ffsdi2.c",
"fixdfdi.c",
"fixdfsi.c",
"fixsfdi.c",
"fixsfsi.c",
"fixunsdfdi.c",
"fixunsdfsi.c",
"fixunssfdi.c",
"fixunssfsi.c",
"fixunsxfdi.c",
"fixunsxfsi.c",
"fixxfdi.c",
"floatdidf.c",
"floatdisf.c",
"floatdixf.c",
"floatsidf.c",
"floatsisf.c",
"floatundidf.c",
"floatundisf.c",
"floatundixf.c",
"floatunsidf.c",
"floatunsisf.c",
"int_util.c",
"lshrdi3.c",
"moddi3.c",
"modsi3.c",
"muldc3.c",
"muldf3.c",
"muldi3.c",
"mulodi4.c",
"mulosi4.c",
"muloti4.c",
"mulsc3.c",
"mulsf3.c",
"mulvdi3.c",
"mulvsi3.c",
"mulxc3.c",
"negdf2.c",
"negdi2.c",
"negsf2.c",
"negvdi2.c",
"negvsi2.c",
"paritydi2.c",
"paritysi2.c",
"popcountdi2.c",
"popcountsi2.c",
"powidf2.c",
"powisf2.c",
"powixf2.c",
"subdf3.c",
"subsf3.c",
"subvdi3.c",
"subvsi3.c",
"truncdfhf2.c",
"truncdfsf2.c",
"truncsfhf2.c",
"ucmpdi2.c",
"udivdi3.c",
"udivmoddi4.c",
"udivmodsi4.c",
"udivsi3.c",
"umoddi3.c",
"umodsi3.c",
];
if !target.contains("ios") {
sources.extend(vec![
"absvti2.c",
"addtf3.c",
"addvti3.c",
"ashlti3.c",
"ashrti3.c",
"clzti2.c",
"cmpti2.c",
"ctzti2.c",
"divtf3.c",
"divti3.c",
"ffsti2.c",
"fixdfti.c",
"fixsfti.c",
"fixunsdfti.c",
"fixunssfti.c",
"fixunsxfti.c",
"fixxfti.c",
"floattidf.c",
"floattisf.c",
"floattixf.c",
"floatuntidf.c",
"floatuntisf.c",
"floatuntixf.c",
"lshrti3.c",
"modti3.c",
"multf3.c",
"multi3.c",
"mulvti3.c",
"negti2.c",
"negvti2.c",
"parityti2.c",
"popcountti2.c",
"powitf2.c",
"subtf3.c",
"subvti3.c",
"trampoline_setup.c",
"ucmpti2.c",
"udivmodti4.c",
"udivti3.c",
"umodti3.c",
]);
}
if target.contains("apple") {
sources.extend(vec![
"atomic_flag_clear.c",
"atomic_flag_clear_explicit.c",
"atomic_flag_test_and_set.c",
"atomic_flag_test_and_set_explicit.c",
"atomic_signal_fence.c",
"atomic_thread_fence.c",
]);
}
if !target.contains("windows") {
sources.push("emutls.c");
}
if target.contains("msvc") {
if target.contains("x86_64") {
sources.extend(vec![
"x86_64/floatdidf.c",
"x86_64/floatdisf.c",
"x86_64/floatdixf.c",
]);
}
} else {
if !target.contains("freebsd") {
sources.push("gcc_personality_v0.c");
}
if target.contains("x86_64") {
sources.extend(vec![
"x86_64/chkstk.S",
"x86_64/chkstk2.S",
"x86_64/floatdidf.c",
"x86_64/floatdisf.c",
"x86_64/floatdixf.c",
"x86_64/floatundidf.S",
"x86_64/floatundisf.S",
"x86_64/floatundixf.S",
]);
}
if target.contains("i386") ||
target.contains("i586") ||
target.contains("i686") {
sources.extend(vec![
"i386/ashldi3.S",
"i386/ashrdi3.S",
"i386/chkstk.S",
"i386/chkstk2.S",
"i386/divdi3.S",
"i386/floatdidf.S",
"i386/floatdisf.S",
"i386/floatdixf.S",
"i386/floatundidf.S",
"i386/floatundisf.S",
"i386/floatundixf.S",
"i386/lshrdi3.S",
"i386/moddi3.S",
"i386/muldi3.S",
"i386/udivdi3.S",
"i386/umoddi3.S",
]);
}
}
if target.contains("arm") && !target.contains("ios") {
sources.extend(vec![
"arm/aeabi_cdcmp.S",
"arm/aeabi_cdcmpeq_check_nan.c",
"arm/aeabi_cfcmp.S",
"arm/aeabi_cfcmpeq_check_nan.c",
"arm/aeabi_dcmp.S",
"arm/aeabi_div0.c",
"arm/aeabi_drsub.c",
"arm/aeabi_fcmp.S",
"arm/aeabi_frsub.c",
"arm/aeabi_idivmod.S",
"arm/aeabi_ldivmod.S",
"arm/aeabi_memcmp.S",
"arm/aeabi_memcpy.S",
"arm/aeabi_memmove.S",
"arm/aeabi_memset.S",
"arm/aeabi_uidivmod.S",
"arm/aeabi_uldivmod.S",
"arm/bswapdi2.S",
"arm/bswapsi2.S",
"arm/clzdi2.S",
"arm/clzsi2.S",
"arm/comparesf2.S",
"arm/divmodsi4.S",
"arm/divsi3.S",
"arm/modsi3.S",
"arm/switch16.S",
"arm/switch32.S",
"arm/switch8.S",
"arm/switchu8.S",
"arm/sync_synchronize.S",
"arm/udivmodsi4.S",
"arm/udivsi3.S",
"arm/umodsi3.S",
]);
}
if target.contains("armv7") {
sources.extend(vec![
"arm/sync_fetch_and_add_4.S",
"arm/sync_fetch_and_add_8.S",
"arm/sync_fetch_and_and_4.S",
"arm/sync_fetch_and_and_8.S",
"arm/sync_fetch_and_max_4.S",
"arm/sync_fetch_and_max_8.S",
"arm/sync_fetch_and_min_4.S",
"arm/sync_fetch_and_min_8.S",
"arm/sync_fetch_and_nand_4.S",
"arm/sync_fetch_and_nand_8.S",
"arm/sync_fetch_and_or_4.S",
"arm/sync_fetch_and_or_8.S",
"arm/sync_fetch_and_sub_4.S",
"arm/sync_fetch_and_sub_8.S",
"arm/sync_fetch_and_umax_4.S",
"arm/sync_fetch_and_umax_8.S",
"arm/sync_fetch_and_umin_4.S",
"arm/sync_fetch_and_umin_8.S",
"arm/sync_fetch_and_xor_4.S",
"arm/sync_fetch_and_xor_8.S",
]);
}
if target.contains("eabihf") {
sources.extend(vec![
"arm/adddf3vfp.S",
"arm/addsf3vfp.S",
"arm/divdf3vfp.S",
"arm/divsf3vfp.S",
"arm/eqdf2vfp.S",
"arm/eqsf2vfp.S",
"arm/extendsfdf2vfp.S",
"arm/fixdfsivfp.S",
"arm/fixsfsivfp.S",
"arm/fixunsdfsivfp.S",
"arm/fixunssfsivfp.S",
"arm/floatsidfvfp.S",
"arm/floatsisfvfp.S",
"arm/floatunssidfvfp.S",
"arm/floatunssisfvfp.S",
"arm/gedf2vfp.S",
"arm/gesf2vfp.S",
"arm/gtdf2vfp.S",
"arm/gtsf2vfp.S",
"arm/ledf2vfp.S",
"arm/lesf2vfp.S",
"arm/ltdf2vfp.S",
"arm/ltsf2vfp.S",
"arm/muldf3vfp.S",
"arm/mulsf3vfp.S",
"arm/negdf2vfp.S",
"arm/negsf2vfp.S",
"arm/nedf2vfp.S",
"arm/nesf2vfp.S",
"arm/restore_vfp_d8_d15_regs.S",
"arm/save_vfp_d8_d15_regs.S",
"arm/subdf3vfp.S",
"arm/subsf3vfp.S",
"arm/truncdfsf2vfp.S",
"arm/unorddf2vfp.S",
"arm/unordsf2vfp.S",
]);
}
if target.contains("aarch64") {
sources.extend(vec![
"comparetf2.c",
"extenddftf2.c",
"extendsftf2.c",
"fixtfdi.c",
"fixtfsi.c",
"fixtfti.c",
"fixunstfdi.c",
"fixunstfsi.c",
"fixunstfti.c",
"floatditf.c",
"floatsitf.c",
"floatunditf.c",
"floatunsitf.c",
"multc3.c",
"trunctfdf2.c",
"trunctfsf2.c",
]);
}
let mut out_of_date = false;
for src in sources {
let src = build.src.join("src/compiler-rt/lib/builtins").join(src);
out_of_date = out_of_date || !up_to_date(&src, &output);
cfg.file(src);
}
if !out_of_date {
return
}
cfg.compile("libcompiler-rt.a");
}
/// Compiles the `rust_test_helpers.c` library which we used in various
/// `run-pass` test suites for ABI testing.
pub fn test_helpers(build: &Build, target: &str) {

View file

@ -75,6 +75,12 @@ pub fn check(build: &mut Build) {
need_cmd("python".as_ref());
// If a manual nodejs was added to the config,
// of if a nodejs install is detected through config, use it.
if let Some(ref s) = build.config.nodejs {
need_cmd(s.as_ref());
}
// We're gonna build some custom C code here and there, host triples
// also build some C++ shims for LLVM so we need a C++ compiler.
for target in build.config.target.iter() {
@ -111,8 +117,8 @@ pub fn check(build: &mut Build) {
// Make sure musl-root is valid if specified
if target.contains("musl") && !target.contains("mips") {
match build.config.musl_root {
Some(ref root) => {
match build.musl_root(target) {
Some(root) => {
if fs::metadata(root.join("lib/libc.a")).is_err() {
panic!("couldn't find libc.a in musl dir: {}",
root.join("lib").display());
@ -123,8 +129,9 @@ pub fn check(build: &mut Build) {
}
}
None => {
panic!("when targeting MUSL the build.musl-root option \
must be specified in config.toml")
panic!("when targeting MUSL either the build.musl-root \
option or the target.$TARGET.musl-root one must \
be specified in config.toml")
}
}
}

View file

@ -82,7 +82,6 @@ macro_rules! targets {
// There aren't really any parameters to this, but empty structs
// with braces are unstable so we just pick something that works.
(llvm, Llvm { _dummy: () }),
(compiler_rt, CompilerRt { _dummy: () }),
(test_helpers, TestHelpers { _dummy: () }),
(debugger_scripts, DebuggerScripts { stage: u32 }),
@ -334,8 +333,7 @@ impl<'a> Step<'a> {
vec![self.libstd(compiler)]
}
Source::Libstd { compiler } => {
vec![self.compiler_rt(()),
self.rustc(compiler.stage).target(compiler.host)]
vec![self.rustc(compiler.stage).target(compiler.host)]
}
Source::LibrustcLink { compiler, host } => {
vec![self.librustc(compiler),
@ -348,7 +346,6 @@ impl<'a> Step<'a> {
vec![self.libstd(compiler),
self.target(host).rustc(compiler.stage)]
}
Source::CompilerRt { _dummy } => Vec::new(),
Source::Llvm { _dummy } => Vec::new(),
Source::TestHelpers { _dummy } => Vec::new(),
Source::DebuggerScripts { stage: _ } => Vec::new(),

View file

@ -23,7 +23,7 @@ use filetime::FileTime;
/// Returns the `name` as the filename of a static library for `target`.
pub fn staticlib(name: &str, target: &str) -> String {
if target.contains("windows-msvc") {
if target.contains("windows") {
format!("{}.lib", name)
} else {
format!("lib{}.a", name)

View file

@ -471,7 +471,7 @@ extern {
fn main() {
println!("You have readline version {} installed.",
rl_readline_version as i32);
unsafe { rl_readline_version as i32 });
}
```
@ -539,6 +539,7 @@ This is currently hidden behind the `abi_vectorcall` gate and is subject to chan
* `system`
* `C`
* `win64`
* `sysv64`
Most of the abis in this list are self-explanatory, but the `system` abi may
seem a little odd. This constraint selects whatever the appropriate ABI is for

View file

@ -54,7 +54,7 @@ binary downloads][install-page].
Oh, we should also mention the officially supported platforms:
* Windows (7, 8, Server 2008 R2)
* Windows (7+)
* Linux (2.6.18 or later, various distributions), x86 and x86-64
* OSX 10.7 (Lion) or greater, x86 and x86-64

View file

@ -152,7 +152,7 @@ the thing `y` points at. Youll notice that `x` had to be marked `mut` as well
If it wasnt, we couldnt take a mutable borrow to an immutable value.
You'll also notice we added an asterisk (`*`) in front of `y`, making it `*y`,
this is because `y` is a `&mut` reference. You'll need to use astrisks to
this is because `y` is a `&mut` reference. You'll need to use asterisks to
access the contents of a reference as well.
Otherwise, `&mut` references are like references. There _is_ a large

View file

@ -275,7 +275,7 @@ wont have its methods:
[write]: ../std/io/trait.Write.html
```rust,ignore
let mut f = std::fs::File::open("foo.txt").expect("Couldnt open foo.txt");
let mut f = std::fs::File::create("foo.txt").expect("Couldnt create foo.txt");
let buf = b"whatever"; // byte string literal. buf: &[u8; 8]
let result = f.write(buf);
# result.unwrap(); // ignore the error
@ -291,10 +291,10 @@ let result = f.write(buf);
We need to `use` the `Write` trait first:
```rust,ignore
```rust,no_run
use std::io::Write;
let mut f = std::fs::File::open("foo.txt").expect("Couldnt open foo.txt");
let mut f = std::fs::File::create("foo.txt").expect("Couldnt create foo.txt");
let buf = b"whatever";
let result = f.write(buf);
# result.unwrap(); // ignore the error

View file

@ -52,7 +52,7 @@ let mut data = vec![1, 2, 3];
let x = &data[0];
// OH NO! `push` causes the backing storage of `data` to be reallocated.
// Dangling pointer! User after free! Alas!
// Dangling pointer! Use after free! Alas!
// (this does not compile in Rust)
data.push(4);

View file

@ -26,10 +26,6 @@ can therefore be trusted. You can use `unsafe` on a trait implementation
to declare that the implementation of that trait has adhered to whatever
contracts the trait's documentation requires.
There is also the `#[unsafe_no_drop_flag]` attribute, which exists for
historic reasons and is being phased out. See the section on [drop flags]
for details.
The standard library has a number of unsafe functions, including:
* `slice::get_unchecked`, which performs unchecked indexing, allowing

View file

@ -1677,6 +1677,7 @@ There are also some platform-specific ABI strings:
* `extern "cdecl"` -- The default for x86\_32 C code.
* `extern "stdcall"` -- The default for the Win32 API on x86\_32.
* `extern "win64"` -- The default for C code on x86\_64 Windows.
* `extern "sysv64"` -- The default for C code on non-Windows x86\_64.
* `extern "aapcs"` -- The default for ARM.
* `extern "fastcall"` -- The `fastcall` ABI -- corresponds to MSVC's
`__fastcall` and GCC and clang's `__attribute__((fastcall))`
@ -2058,10 +2059,6 @@ macro scope.
outside of its dynamic extent), and thus this attribute has the word
"unsafe" in its name. To use this, the
`unsafe_destructor_blind_to_params` feature gate must be enabled.
- `unsafe_no_drop_flag` - on structs, remove the flag that prevents
destructors from being run twice. Destructors might be run multiple times on
the same object with this attribute. To use this, the `unsafe_no_drop_flag` feature
gate must be enabled.
- `doc` - Doc comments such as `/// foo` are equivalent to `#[doc = "foo"]`.
- `rustc_on_unimplemented` - Write a custom note to be shown along with the error
when the trait is found to be unimplemented on a type.
@ -2070,6 +2067,9 @@ macro scope.
trait of the same name. `{Self}` will be replaced with the type that is supposed
to implement the trait but doesn't. To use this, the `on_unimplemented` feature gate
must be enabled.
- `must_use` - on structs and enums, will warn if a value of this type isn't used or
assigned to a variable. You may also include an optional message by using
`#[must_use = "message"]` which will be given alongside the warning.
### Conditional compilation
@ -2441,6 +2441,9 @@ The currently implemented features of the reference compiler are:
into a Rust program. This capability, especially the signature for the
annotated function, is subject to change.
* `static_in_const` - Enables lifetime elision with a `'static` default for
`const` and `static` item declarations.
* `thread_local` - The usage of the `#[thread_local]` attribute is experimental
and should be seen as unstable. This attribute is used to
declare a `static` as being unique per-thread leveraging
@ -2454,12 +2457,6 @@ The currently implemented features of the reference compiler are:
* `unboxed_closures` - Rust's new closure design, which is currently a work in
progress feature with many known bugs.
* `unsafe_no_drop_flag` - Allows use of the `#[unsafe_no_drop_flag]` attribute,
which removes hidden flag added to a type that
implements the `Drop` trait. The design for the
`Drop` flag is subject to change, and this feature
may be removed in the future.
* `unmarked_api` - Allows use of items within a `#![staged_api]` crate
which have not been marked with a stability marker.
Such items should not be allowed by the compiler to exist,
@ -2485,6 +2482,9 @@ The currently implemented features of the reference compiler are:
* - `dotdot_in_tuple_patterns` - Allows `..` in tuple (struct) patterns.
* - `abi_sysv64` - Allows the usage of the system V AMD64 calling convention
(e.g. `extern "sysv64" func fn_();`)
If a feature is promoted to a language feature, then all existing programs will
start to receive compilation warnings about `#![feature]` directives which enabled
the new feature (because the directive is no longer necessary). However, if a

View file

@ -331,6 +331,33 @@ impl<T: ?Sized> Arc<T> {
deallocate(ptr as *mut u8, size_of_val(&*ptr), align_of_val(&*ptr))
}
}
#[inline]
#[unstable(feature = "ptr_eq",
reason = "newly added",
issue = "36497")]
/// Return whether two `Arc` references point to the same value
/// (not just values that compare equal).
///
/// # Examples
///
/// ```
/// #![feature(ptr_eq)]
///
/// use std::sync::Arc;
///
/// let five = Arc::new(5);
/// let same_five = five.clone();
/// let other_five = Arc::new(5);
///
/// assert!(Arc::ptr_eq(&five, &same_five));
/// assert!(!Arc::ptr_eq(&five, &other_five));
/// ```
pub fn ptr_eq(this: &Self, other: &Self) -> bool {
let this_ptr: *const ArcInner<T> = *this.ptr;
let other_ptr: *const ArcInner<T> = *other.ptr;
this_ptr == other_ptr
}
}
#[stable(feature = "rust1", since = "1.0.0")]
@ -718,6 +745,7 @@ impl<T: ?Sized> Clone for Weak<T> {
#[stable(feature = "downgraded_weak", since = "1.10.0")]
impl<T> Default for Weak<T> {
/// Constructs a new `Weak<T>` without an accompanying instance of T.
fn default() -> Weak<T> {
Weak::new()
}
@ -923,6 +951,7 @@ impl<T: ?Sized> fmt::Pointer for Arc<T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Default> Default for Arc<T> {
/// Creates a new `Arc<T>`, with the `Default` value for T.
fn default() -> Arc<T> {
Arc::new(Default::default())
}
@ -1198,6 +1227,16 @@ mod tests {
let foo: Weak<usize> = Weak::new();
assert!(foo.upgrade().is_none());
}
#[test]
fn test_ptr_eq() {
let five = Arc::new(5);
let same_five = five.clone();
let other_five = Arc::new(5);
assert!(Arc::ptr_eq(&five, &same_five));
assert!(!Arc::ptr_eq(&five, &other_five));
}
}
#[stable(feature = "rust1", since = "1.0.0")]

View file

@ -290,6 +290,7 @@ impl<T: ?Sized> Box<T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Default> Default for Box<T> {
/// Creates a `Box<T>`, with the `Default` value for T.
fn default() -> Box<T> {
box Default::default()
}

View file

@ -376,6 +376,33 @@ impl<T: ?Sized> Rc<T> {
None
}
}
#[inline]
#[unstable(feature = "ptr_eq",
reason = "newly added",
issue = "36497")]
/// Return whether two `Rc` references point to the same value
/// (not just values that compare equal).
///
/// # Examples
///
/// ```
/// #![feature(ptr_eq)]
///
/// use std::rc::Rc;
///
/// let five = Rc::new(5);
/// let same_five = five.clone();
/// let other_five = Rc::new(5);
///
/// assert!(Rc::ptr_eq(&five, &same_five));
/// assert!(!Rc::ptr_eq(&five, &other_five));
/// ```
pub fn ptr_eq(this: &Self, other: &Self) -> bool {
let this_ptr: *const RcBox<T> = *this.ptr;
let other_ptr: *const RcBox<T> = *other.ptr;
this_ptr == other_ptr
}
}
impl<T: Clone> Rc<T> {
@ -870,6 +897,7 @@ impl<T: ?Sized + fmt::Debug> fmt::Debug for Weak<T> {
#[stable(feature = "downgraded_weak", since = "1.10.0")]
impl<T> Default for Weak<T> {
/// Creates a new `Weak<T>`.
fn default() -> Weak<T> {
Weak::new()
}
@ -1173,6 +1201,16 @@ mod tests {
let foo: Weak<usize> = Weak::new();
assert!(foo.upgrade().is_none());
}
#[test]
fn test_ptr_eq() {
let five = Rc::new(5);
let same_five = five.clone();
let other_five = Rc::new(5);
assert!(Rc::ptr_eq(&five, &same_five));
assert!(!Rc::ptr_eq(&five, &other_five));
}
}
#[stable(feature = "rust1", since = "1.0.0")]

View file

@ -77,7 +77,9 @@ const MIN_ALIGN: usize = 8;
#[cfg(all(any(target_arch = "x86",
target_arch = "x86_64",
target_arch = "aarch64",
target_arch = "powerpc64")))]
target_arch = "powerpc64",
target_arch = "mips64",
target_arch = "s390x")))]
const MIN_ALIGN: usize = 16;
// MALLOCX_ALIGN(a) macro

View file

@ -32,7 +32,9 @@
target_arch = "asmjs")))]
const MIN_ALIGN: usize = 8;
#[cfg(all(any(target_arch = "x86_64",
target_arch = "aarch64")))]
target_arch = "aarch64",
target_arch = "mips64",
target_arch = "s390x")))]
const MIN_ALIGN: usize = 16;
#[no_mangle]

View file

@ -15,9 +15,8 @@
//! of individual objects while the arena itself is still alive. The benefit
//! of an arena is very fast allocation; just a pointer bump.
//!
//! This crate has two arenas implemented: `TypedArena`, which is a simpler
//! arena but can only hold objects of a single type, and `Arena`, which is a
//! more complex, slower arena which can hold objects of any type.
//! This crate implements `TypedArena`, a simple arena that can only hold
//! objects of a single type.
#![crate_name = "arena"]
#![unstable(feature = "rustc_private", issue = "27812")]
@ -51,8 +50,11 @@ use std::ptr;
use alloc::heap;
use alloc::raw_vec::RawVec;
/// A faster arena that can hold objects of only one type.
/// An arena that can hold objects of only one type.
pub struct TypedArena<T> {
/// The capacity of the first chunk (once it is allocated).
first_chunk_capacity: usize,
/// A pointer to the next object to be allocated.
ptr: Cell<*mut T>,
@ -60,7 +62,7 @@ pub struct TypedArena<T> {
/// reached, a new chunk is allocated.
end: Cell<*mut T>,
/// A vector arena segments.
/// A vector of arena chunks.
chunks: RefCell<Vec<TypedArenaChunk<T>>>,
/// Marker indicating that dropping the arena causes its owned
@ -69,7 +71,7 @@ pub struct TypedArena<T> {
}
struct TypedArenaChunk<T> {
/// Pointer to the next arena segment.
/// The raw storage for the arena chunk.
storage: RawVec<T>,
}
@ -117,7 +119,7 @@ impl<T> TypedArenaChunk<T> {
const PAGE: usize = 4096;
impl<T> TypedArena<T> {
/// Creates a new `TypedArena` with preallocated space for many objects.
/// Creates a new `TypedArena`.
#[inline]
pub fn new() -> TypedArena<T> {
// Reserve at least one page.
@ -125,18 +127,18 @@ impl<T> TypedArena<T> {
TypedArena::with_capacity(PAGE / elem_size)
}
/// Creates a new `TypedArena` with preallocated space for the given number of
/// objects.
/// Creates a new `TypedArena`. Each chunk used within the arena will have
/// space for at least the given number of objects.
#[inline]
pub fn with_capacity(capacity: usize) -> TypedArena<T> {
unsafe {
let chunk = TypedArenaChunk::<T>::new(cmp::max(1, capacity));
TypedArena {
ptr: Cell::new(chunk.start()),
end: Cell::new(chunk.end()),
chunks: RefCell::new(vec![chunk]),
_own: PhantomData,
}
TypedArena {
first_chunk_capacity: cmp::max(1, capacity),
// We set both `ptr` and `end` to 0 so that the first call to
// alloc() will trigger a grow().
ptr: Cell::new(0 as *mut T),
end: Cell::new(0 as *mut T),
chunks: RefCell::new(vec![]),
_own: PhantomData,
}
}
@ -171,16 +173,22 @@ impl<T> TypedArena<T> {
fn grow(&self) {
unsafe {
let mut chunks = self.chunks.borrow_mut();
let prev_capacity = chunks.last().unwrap().storage.cap();
let new_capacity = prev_capacity.checked_mul(2).unwrap();
if chunks.last_mut().unwrap().storage.double_in_place() {
self.end.set(chunks.last().unwrap().end());
let (chunk, new_capacity);
if let Some(last_chunk) = chunks.last_mut() {
if last_chunk.storage.double_in_place() {
self.end.set(last_chunk.end());
return;
} else {
let prev_capacity = last_chunk.storage.cap();
new_capacity = prev_capacity.checked_mul(2).unwrap();
}
} else {
let chunk = TypedArenaChunk::<T>::new(new_capacity);
self.ptr.set(chunk.start());
self.end.set(chunk.end());
chunks.push(chunk);
new_capacity = self.first_chunk_capacity;
}
chunk = TypedArenaChunk::<T>::new(new_capacity);
self.ptr.set(chunk.start());
self.end.set(chunk.end());
chunks.push(chunk);
}
}
/// Clears the arena. Deallocates all but the longest chunk which may be reused.
@ -188,12 +196,14 @@ impl<T> TypedArena<T> {
unsafe {
// Clear the last chunk, which is partially filled.
let mut chunks_borrow = self.chunks.borrow_mut();
let last_idx = chunks_borrow.len() - 1;
self.clear_last_chunk(&mut chunks_borrow[last_idx]);
// If `T` is ZST, code below has no effect.
for mut chunk in chunks_borrow.drain(..last_idx) {
let cap = chunk.storage.cap();
chunk.destroy(cap);
if let Some(mut last_chunk) = chunks_borrow.pop() {
self.clear_last_chunk(&mut last_chunk);
// If `T` is ZST, code below has no effect.
for mut chunk in chunks_borrow.drain(..) {
let cap = chunk.storage.cap();
chunk.destroy(cap);
}
chunks_borrow.push(last_chunk);
}
}
}
@ -230,13 +240,14 @@ impl<T> Drop for TypedArena<T> {
unsafe {
// Determine how much was filled.
let mut chunks_borrow = self.chunks.borrow_mut();
let mut last_chunk = chunks_borrow.pop().unwrap();
// Drop the contents of the last chunk.
self.clear_last_chunk(&mut last_chunk);
// The last chunk will be dropped. Destroy all other chunks.
for chunk in chunks_borrow.iter_mut() {
let cap = chunk.storage.cap();
chunk.destroy(cap);
if let Some(mut last_chunk) = chunks_borrow.pop() {
// Drop the contents of the last chunk.
self.clear_last_chunk(&mut last_chunk);
// The last chunk will be dropped. Destroy all other chunks.
for chunk in chunks_borrow.iter_mut() {
let cap = chunk.storage.cap();
chunk.destroy(cap);
}
}
// RawVec handles deallocation of `last_chunk` and `self.chunks`.
}
@ -260,6 +271,12 @@ mod tests {
z: i32,
}
#[test]
pub fn test_unused() {
let arena: TypedArena<Point> = TypedArena::new();
assert!(arena.chunks.borrow().is_empty());
}
#[test]
fn test_arena_alloc_nested() {
struct Inner {

View file

@ -263,6 +263,7 @@ impl<T: Clone> Clone for BinaryHeap<T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Ord> Default for BinaryHeap<T> {
/// Creates an empty `BinaryHeap<T>`.
#[inline]
fn default() -> BinaryHeap<T> {
BinaryHeap::new()
@ -884,58 +885,61 @@ struct Hole<'a, T: 'a> {
impl<'a, T> Hole<'a, T> {
/// Create a new Hole at index `pos`.
fn new(data: &'a mut [T], pos: usize) -> Self {
unsafe {
let elt = ptr::read(&data[pos]);
Hole {
data: data,
elt: Some(elt),
pos: pos,
}
///
/// Unsafe because pos must be within the data slice.
#[inline]
unsafe fn new(data: &'a mut [T], pos: usize) -> Self {
debug_assert!(pos < data.len());
let elt = ptr::read(&data[pos]);
Hole {
data: data,
elt: Some(elt),
pos: pos,
}
}
#[inline(always)]
#[inline]
fn pos(&self) -> usize {
self.pos
}
/// Return a reference to the element removed
#[inline(always)]
#[inline]
fn element(&self) -> &T {
self.elt.as_ref().unwrap()
}
/// Return a reference to the element at `index`.
///
/// Panics if the index is out of bounds.
///
/// Unsafe because index must not equal pos.
#[inline(always)]
/// Unsafe because index must be within the data slice and not equal to pos.
#[inline]
unsafe fn get(&self, index: usize) -> &T {
debug_assert!(index != self.pos);
&self.data[index]
debug_assert!(index < self.data.len());
self.data.get_unchecked(index)
}
/// Move hole to new location
///
/// Unsafe because index must not equal pos.
#[inline(always)]
/// Unsafe because index must be within the data slice and not equal to pos.
#[inline]
unsafe fn move_to(&mut self, index: usize) {
debug_assert!(index != self.pos);
let index_ptr: *const _ = &self.data[index];
let hole_ptr = &mut self.data[self.pos];
debug_assert!(index < self.data.len());
let index_ptr: *const _ = self.data.get_unchecked(index);
let hole_ptr = self.data.get_unchecked_mut(self.pos);
ptr::copy_nonoverlapping(index_ptr, hole_ptr, 1);
self.pos = index;
}
}
impl<'a, T> Drop for Hole<'a, T> {
#[inline]
fn drop(&mut self) {
// fill the hole again
unsafe {
let pos = self.pos;
ptr::write(&mut self.data[pos], self.elt.take().unwrap());
ptr::write(self.data.get_unchecked_mut(pos), self.elt.take().unwrap());
}
}
}

View file

@ -249,6 +249,7 @@ impl<'a, B: ?Sized> Default for Cow<'a, B>
where B: ToOwned,
<B as ToOwned>::Owned: Default
{
/// Creates an owned Cow<'a, B> with the default value for the contained owned value.
fn default() -> Cow<'a, B> {
Owned(<B as ToOwned>::Owned::default())
}

View file

@ -56,8 +56,12 @@ use self::Entry::*;
/// however, performance is excellent.
///
/// It is a logic error for a key to be modified in such a way that the key's ordering relative to
/// any other key, as determined by the `Ord` trait, changes while it is in the map. This is
/// normally only possible through `Cell`, `RefCell`, global state, I/O, or unsafe code.
/// any other key, as determined by the [`Ord`] trait, changes while it is in the map. This is
/// normally only possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code.
///
/// [`Ord`]: ../../std/cmp/trait.Ord.html
/// [`Cell`]: ../../std/cell/struct.Cell.html
/// [`RefCell`]: ../../std/cell/struct.RefCell.html
///
/// # Examples
///
@ -1663,6 +1667,7 @@ impl<K: Hash, V: Hash> Hash for BTreeMap<K, V> {
}
impl<K: Ord, V> Default for BTreeMap<K, V> {
/// Creates an empty `BTreeMap<K, V>`.
fn default() -> BTreeMap<K, V> {
BTreeMap::new()
}
@ -2020,7 +2025,7 @@ impl<'a, K: Ord, V> VacantEntry<'a, K, V> {
self.key
}
/// Sets the value of the entry with the VacantEntry's key,
/// Sets the value of the entry with the `VacantEntry`'s key,
/// and returns a mutable reference to it.
///
/// # Examples
@ -2192,7 +2197,7 @@ impl<'a, K: Ord, V> OccupiedEntry<'a, K, V> {
self.handle.into_kv_mut().1
}
/// Sets the value of the entry with the OccupiedEntry's key,
/// Sets the value of the entry with the `OccupiedEntry`'s key,
/// and returns the entry's old value.
///
/// # Examples

View file

@ -674,6 +674,7 @@ impl<'a, T: 'a + Ord + Copy> Extend<&'a T> for BTreeSet<T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Ord> Default for BTreeSet<T> {
/// Makes an empty `BTreeSet<T>` with a reasonable choice of B.
fn default() -> BTreeSet<T> {
BTreeSet::new()
}

View file

@ -164,6 +164,7 @@ impl<T> LinkedList<T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Default for LinkedList<T> {
/// Creates an empty `LinkedList<T>`.
#[inline]
fn default() -> Self {
Self::new()

View file

@ -1594,6 +1594,49 @@ impl str {
result
}
/// Replaces first N matches of a pattern with another string.
///
/// `replacen` creates a new [`String`], and copies the data from this string slice into it.
/// While doing so, it attempts to find matches of a pattern. If it finds any, it
/// replaces them with the replacement string slice at most `N` times.
///
/// [`String`]: string/struct.String.html
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// # #![feature(str_replacen)]
/// let s = "foo foo 123 foo";
/// assert_eq!("new new 123 foo", s.replacen("foo", "new", 2));
/// assert_eq!("faa fao 123 foo", s.replacen('o', "a", 3));
/// assert_eq!("foo foo new23 foo", s.replacen(char::is_numeric, "new", 1));
/// ```
///
/// When the pattern doesn't match:
///
/// ```
/// # #![feature(str_replacen)]
/// let s = "this is old";
/// assert_eq!(s, s.replacen("cookie monster", "little lamb", 10));
/// ```
#[unstable(feature = "str_replacen",
issue = "36436",
reason = "only need to replace first N matches")]
pub fn replacen<'a, P: Pattern<'a>>(&'a self, pat: P, to: &str, count: usize) -> String {
// Hope to reduce the times of re-allocation
let mut result = String::with_capacity(32);
let mut last_end = 0;
for (start, part) in self.match_indices(pat).take(count) {
result.push_str(unsafe { self.slice_unchecked(last_end, start) });
result.push_str(to);
last_end = start + part.len();
}
result.push_str(unsafe { self.slice_unchecked(last_end, self.len()) });
result
}
/// Returns the lowercase equivalent of this string slice, as a new [`String`].
///
/// 'Lowercase' is defined according to the terms of the Unicode Derived Core Property

View file

@ -1567,6 +1567,7 @@ impl_eq! { Cow<'a, str>, String }
#[stable(feature = "rust1", since = "1.0.0")]
impl Default for String {
/// Creates an empty `String`.
#[inline]
fn default() -> String {
String::new()

View file

@ -1046,21 +1046,27 @@ impl<T: Clone> Vec<T> {
self.reserve(n);
unsafe {
let len = self.len();
let mut ptr = self.as_mut_ptr().offset(len as isize);
let mut ptr = self.as_mut_ptr().offset(self.len() as isize);
// Use SetLenOnDrop to work around bug where compiler
// may not realize the store through `ptr` trough self.set_len()
// don't alias.
let mut local_len = SetLenOnDrop::new(&mut self.len);
// Write all elements except the last one
for i in 1..n {
for _ in 1..n {
ptr::write(ptr, value.clone());
ptr = ptr.offset(1);
// Increment the length in every step in case clone() panics
self.set_len(len + i);
local_len.increment_len(1);
}
if n > 0 {
// We can write the last element directly without cloning needlessly
ptr::write(ptr, value);
self.set_len(len + n);
local_len.increment_len(1);
}
// len set by scope guard
}
}
@ -1085,20 +1091,56 @@ impl<T: Clone> Vec<T> {
pub fn extend_from_slice(&mut self, other: &[T]) {
self.reserve(other.len());
for i in 0..other.len() {
// Unsafe code so this can be optimised to a memcpy (or something
// similarly fast) when T is Copy. LLVM is easily confused, so any
// extra operations during the loop can prevent this optimisation.
unsafe {
let len = self.len();
let ptr = self.get_unchecked_mut(len) as *mut T;
// Use SetLenOnDrop to work around bug where compiler
// may not realize the store through `ptr` trough self.set_len()
// don't alias.
let mut local_len = SetLenOnDrop::new(&mut self.len);
// Unsafe code so this can be optimised to a memcpy (or something
// similarly fast) when T is Copy. LLVM is easily confused, so any
// extra operations during the loop can prevent this optimisation.
unsafe {
ptr::write(self.get_unchecked_mut(len), other.get_unchecked(i).clone());
self.set_len(len + 1);
for i in 0..other.len() {
ptr::write(ptr.offset(i as isize), other.get_unchecked(i).clone());
local_len.increment_len(1);
}
// len set by scope guard
}
}
}
// Set the length of the vec when the `SetLenOnDrop` value goes out of scope.
//
// The idea is: The length field in SetLenOnDrop is a local variable
// that the optimizer will see does not alias with any stores through the Vec's data
// pointer. This is a workaround for alias analysis issue #32155
struct SetLenOnDrop<'a> {
len: &'a mut usize,
local_len: usize,
}
impl<'a> SetLenOnDrop<'a> {
#[inline]
fn new(len: &'a mut usize) -> Self {
SetLenOnDrop { local_len: *len, len: len }
}
#[inline]
fn increment_len(&mut self, increment: usize) {
self.local_len += increment;
}
}
impl<'a> Drop for SetLenOnDrop<'a> {
#[inline]
fn drop(&mut self) {
*self.len = self.local_len;
}
}
impl<T: PartialEq> Vec<T> {
/// Removes consecutive repeated elements in the vector.
///
@ -1610,6 +1652,7 @@ impl<T> Drop for Vec<T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Default for Vec<T> {
/// Creates an empty `Vec<T>`.
fn default() -> Vec<T> {
Vec::new()
}

View file

@ -84,6 +84,7 @@ impl<T> Drop for VecDeque<T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Default for VecDeque<T> {
/// Creates an empty `VecDeque<T>`.
#[inline]
fn default() -> VecDeque<T> {
VecDeque::new()

View file

@ -39,30 +39,8 @@ fn test_hash() {
assert!(::hash(&x) == ::hash(&y));
}
struct Counter<'a, 'b> {
i: &'a mut usize,
expected: &'b [i32],
}
impl<'a, 'b, 'c> FnMut<(&'c i32,)> for Counter<'a, 'b> {
extern "rust-call" fn call_mut(&mut self, (&x,): (&'c i32,)) -> bool {
assert_eq!(x, self.expected[*self.i]);
*self.i += 1;
true
}
}
impl<'a, 'b, 'c> FnOnce<(&'c i32,)> for Counter<'a, 'b> {
type Output = bool;
extern "rust-call" fn call_once(mut self, args: (&'c i32,)) -> bool {
self.call_mut(args)
}
}
fn check<F>(a: &[i32], b: &[i32], expected: &[i32], f: F) where
// FIXME Replace Counter with `Box<FnMut(_) -> _>`
F: FnOnce(&BTreeSet<i32>, &BTreeSet<i32>, Counter) -> bool,
F: FnOnce(&BTreeSet<i32>, &BTreeSet<i32>, &mut FnMut(&i32) -> bool) -> bool,
{
let mut set_a = BTreeSet::new();
let mut set_b = BTreeSet::new();
@ -71,7 +49,11 @@ fn check<F>(a: &[i32], b: &[i32], expected: &[i32], f: F) where
for y in b { assert!(set_b.insert(*y)) }
let mut i = 0;
f(&set_a, &set_b, Counter { i: &mut i, expected: expected });
f(&set_a, &set_b, &mut |&x| {
assert_eq!(x, expected[i]);
i += 1;
true
});
assert_eq!(i, expected.len());
}

View file

@ -16,12 +16,12 @@
#![feature(collections)]
#![feature(collections_bound)]
#![feature(const_fn)]
#![feature(fn_traits)]
#![feature(enumset)]
#![feature(pattern)]
#![feature(rand)]
#![feature(step_by)]
#![feature(str_escape)]
#![feature(str_replacen)]
#![feature(test)]
#![feature(unboxed_closures)]
#![feature(unicode)]

View file

@ -218,6 +218,20 @@ fn test_is_empty() {
assert!(!"a".is_empty());
}
#[test]
fn test_replacen() {
assert_eq!("".replacen('a', "b", 5), "");
assert_eq!("acaaa".replacen("a", "b", 3), "bcbba");
assert_eq!("aaaa".replacen("a", "b", 0), "aaaa");
let test = "test";
assert_eq!(" test test ".replacen(test, "toast", 3), " toast toast ");
assert_eq!(" test test ".replacen(test, "toast", 0), " test test ");
assert_eq!(" test test ".replacen(test, "", 5), " ");
assert_eq!("qwer123zxc789".replacen(char::is_numeric, "", 3), "qwerzxc789");
}
#[test]
fn test_replace() {
let a = "a";

View file

@ -0,0 +1,15 @@
[package]
authors = ["The Rust Project Developers"]
build = "build.rs"
name = "compiler_builtins"
version = "0.0.0"
[lib]
name = "compiler_builtins"
path = "lib.rs"
[dependencies]
core = { path = "../libcore" }
[build-dependencies]
gcc = "0.3.27"

View file

@ -0,0 +1,404 @@
// 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.
//! Compiles the `compiler-rt` library, or at least the builtins part of it.
//!
//! Note that while compiler-rt has a build system associated with it, we
//! specifically don't use it here. The compiler-rt build system, written in
//! CMake, is actually *very* difficult to work with in terms of getting it to
//! compile on all the relevant platforms we want it to compile on. In the end
//! it became so much pain to work with local patches, work around the oddities
//! of the build system, etc, that we're just building everything by hand now.
//!
//! In general compiler-rt is just a bunch of intrinsics that are in practice
//! *very* stable. We just need to make sure that all the relevant functions and
//! such are compiled somewhere and placed in an object file somewhere.
//! Eventually, these should all be written in Rust!
//!
//! So below you'll find a listing of every single file in the compiler-rt repo
//! that we're compiling. We just reach in and compile with the `gcc` crate
//! which should have all the relevant flags and such already configured.
//!
//! The risk here is that if we update compiler-rt we may need to compile some
//! new intrinsics, but to be honest we surely don't use all of the intrinsics
//! listed below today so the likelihood of us actually needing a new intrinsic
//! is quite low. The failure case is also just that someone reports a link
//! error (if any) and then we just add it to the list. Overall, that cost is
//! far far less than working with compiler-rt's build system over time.
extern crate gcc;
use std::collections::BTreeMap;
use std::env;
use std::path::Path;
struct Sources {
// SYMBOL -> PATH TO SOURCE
map: BTreeMap<&'static str, &'static str>,
}
impl Sources {
fn new() -> Sources {
Sources { map: BTreeMap::new() }
}
fn extend(&mut self, sources: &[&'static str]) {
// NOTE Some intrinsics have both a generic implementation (e.g.
// `floatdidf.c`) and an arch optimized implementation
// (`x86_64/floatdidf.c`). In those cases, we keep the arch optimized
// implementation and discard the generic implementation. If we don't
// and keep both implementations, the linker will yell at us about
// duplicate symbols!
for &src in sources {
let symbol = Path::new(src).file_stem().unwrap().to_str().unwrap();
if src.contains("/") {
// Arch-optimized implementation (preferred)
self.map.insert(symbol, src);
} else {
// Generic implementation
if !self.map.contains_key(symbol) {
self.map.insert(symbol, src);
}
}
}
}
}
fn main() {
let target = env::var("TARGET").unwrap();
let cfg = &mut gcc::Config::new();
if target.contains("msvc") {
// Don't pull in extra libraries on MSVC
cfg.flag("/Zl");
// Emulate C99 and C++11's __func__ for MSVC prior to 2013 CTP
cfg.define("__func__", Some("__FUNCTION__"));
} else {
// Turn off various features of gcc and such, mostly copying
// compiler-rt's build system already
cfg.flag("-fno-builtin");
cfg.flag("-fvisibility=hidden");
cfg.flag("-fomit-frame-pointer");
cfg.flag("-ffreestanding");
}
let mut sources = Sources::new();
sources.extend(&["absvdi2.c",
"absvsi2.c",
"adddf3.c",
"addsf3.c",
"addvdi3.c",
"addvsi3.c",
"apple_versioning.c",
"ashldi3.c",
"ashrdi3.c",
"clear_cache.c",
"clzdi2.c",
"clzsi2.c",
"cmpdi2.c",
"comparedf2.c",
"comparesf2.c",
"ctzdi2.c",
"ctzsi2.c",
"divdc3.c",
"divdf3.c",
"divdi3.c",
"divmoddi4.c",
"divmodsi4.c",
"divsc3.c",
"divsf3.c",
"divsi3.c",
"divxc3.c",
"extendsfdf2.c",
"extendhfsf2.c",
"ffsdi2.c",
"fixdfdi.c",
"fixdfsi.c",
"fixsfdi.c",
"fixsfsi.c",
"fixunsdfdi.c",
"fixunsdfsi.c",
"fixunssfdi.c",
"fixunssfsi.c",
"fixunsxfdi.c",
"fixunsxfsi.c",
"fixxfdi.c",
"floatdidf.c",
"floatdisf.c",
"floatdixf.c",
"floatsidf.c",
"floatsisf.c",
"floatundidf.c",
"floatundisf.c",
"floatundixf.c",
"floatunsidf.c",
"floatunsisf.c",
"int_util.c",
"lshrdi3.c",
"moddi3.c",
"modsi3.c",
"muldc3.c",
"muldf3.c",
"muldi3.c",
"mulodi4.c",
"mulosi4.c",
"muloti4.c",
"mulsc3.c",
"mulsf3.c",
"mulvdi3.c",
"mulvsi3.c",
"mulxc3.c",
"negdf2.c",
"negdi2.c",
"negsf2.c",
"negvdi2.c",
"negvsi2.c",
"paritydi2.c",
"paritysi2.c",
"popcountdi2.c",
"popcountsi2.c",
"powidf2.c",
"powisf2.c",
"powixf2.c",
"subdf3.c",
"subsf3.c",
"subvdi3.c",
"subvsi3.c",
"truncdfhf2.c",
"truncdfsf2.c",
"truncsfhf2.c",
"ucmpdi2.c",
"udivdi3.c",
"udivmoddi4.c",
"udivmodsi4.c",
"udivsi3.c",
"umoddi3.c",
"umodsi3.c"]);
if !target.contains("ios") {
sources.extend(&["absvti2.c",
"addtf3.c",
"addvti3.c",
"ashlti3.c",
"ashrti3.c",
"clzti2.c",
"cmpti2.c",
"ctzti2.c",
"divtf3.c",
"divti3.c",
"ffsti2.c",
"fixdfti.c",
"fixsfti.c",
"fixunsdfti.c",
"fixunssfti.c",
"fixunsxfti.c",
"fixxfti.c",
"floattidf.c",
"floattisf.c",
"floattixf.c",
"floatuntidf.c",
"floatuntisf.c",
"floatuntixf.c",
"lshrti3.c",
"modti3.c",
"multf3.c",
"multi3.c",
"mulvti3.c",
"negti2.c",
"negvti2.c",
"parityti2.c",
"popcountti2.c",
"powitf2.c",
"subtf3.c",
"subvti3.c",
"trampoline_setup.c",
"ucmpti2.c",
"udivmodti4.c",
"udivti3.c",
"umodti3.c"]);
}
if target.contains("apple") {
sources.extend(&["atomic_flag_clear.c",
"atomic_flag_clear_explicit.c",
"atomic_flag_test_and_set.c",
"atomic_flag_test_and_set_explicit.c",
"atomic_signal_fence.c",
"atomic_thread_fence.c"]);
}
if !target.contains("windows") {
sources.extend(&["emutls.c"]);
}
if target.contains("msvc") {
if target.contains("x86_64") {
sources.extend(&["x86_64/floatdidf.c", "x86_64/floatdisf.c", "x86_64/floatdixf.c"]);
}
} else {
if !target.contains("freebsd") {
sources.extend(&["gcc_personality_v0.c"]);
}
if target.contains("x86_64") {
sources.extend(&["x86_64/chkstk.S",
"x86_64/chkstk2.S",
"x86_64/floatdidf.c",
"x86_64/floatdisf.c",
"x86_64/floatdixf.c",
"x86_64/floatundidf.S",
"x86_64/floatundisf.S",
"x86_64/floatundixf.S"]);
}
if target.contains("i386") || target.contains("i586") || target.contains("i686") {
sources.extend(&["i386/ashldi3.S",
"i386/ashrdi3.S",
"i386/chkstk.S",
"i386/chkstk2.S",
"i386/divdi3.S",
"i386/floatdidf.S",
"i386/floatdisf.S",
"i386/floatdixf.S",
"i386/floatundidf.S",
"i386/floatundisf.S",
"i386/floatundixf.S",
"i386/lshrdi3.S",
"i386/moddi3.S",
"i386/muldi3.S",
"i386/udivdi3.S",
"i386/umoddi3.S"]);
}
}
if target.contains("arm") && !target.contains("ios") {
sources.extend(&["arm/aeabi_cdcmp.S",
"arm/aeabi_cdcmpeq_check_nan.c",
"arm/aeabi_cfcmp.S",
"arm/aeabi_cfcmpeq_check_nan.c",
"arm/aeabi_dcmp.S",
"arm/aeabi_div0.c",
"arm/aeabi_drsub.c",
"arm/aeabi_fcmp.S",
"arm/aeabi_frsub.c",
"arm/aeabi_idivmod.S",
"arm/aeabi_ldivmod.S",
"arm/aeabi_memcmp.S",
"arm/aeabi_memcpy.S",
"arm/aeabi_memmove.S",
"arm/aeabi_memset.S",
"arm/aeabi_uidivmod.S",
"arm/aeabi_uldivmod.S",
"arm/bswapdi2.S",
"arm/bswapsi2.S",
"arm/clzdi2.S",
"arm/clzsi2.S",
"arm/comparesf2.S",
"arm/divmodsi4.S",
"arm/divsi3.S",
"arm/modsi3.S",
"arm/switch16.S",
"arm/switch32.S",
"arm/switch8.S",
"arm/switchu8.S",
"arm/sync_synchronize.S",
"arm/udivmodsi4.S",
"arm/udivsi3.S",
"arm/umodsi3.S"]);
}
if target.contains("armv7") {
sources.extend(&["arm/sync_fetch_and_add_4.S",
"arm/sync_fetch_and_add_8.S",
"arm/sync_fetch_and_and_4.S",
"arm/sync_fetch_and_and_8.S",
"arm/sync_fetch_and_max_4.S",
"arm/sync_fetch_and_max_8.S",
"arm/sync_fetch_and_min_4.S",
"arm/sync_fetch_and_min_8.S",
"arm/sync_fetch_and_nand_4.S",
"arm/sync_fetch_and_nand_8.S",
"arm/sync_fetch_and_or_4.S",
"arm/sync_fetch_and_or_8.S",
"arm/sync_fetch_and_sub_4.S",
"arm/sync_fetch_and_sub_8.S",
"arm/sync_fetch_and_umax_4.S",
"arm/sync_fetch_and_umax_8.S",
"arm/sync_fetch_and_umin_4.S",
"arm/sync_fetch_and_umin_8.S",
"arm/sync_fetch_and_xor_4.S",
"arm/sync_fetch_and_xor_8.S"]);
}
if target.contains("eabihf") {
sources.extend(&["arm/adddf3vfp.S",
"arm/addsf3vfp.S",
"arm/divdf3vfp.S",
"arm/divsf3vfp.S",
"arm/eqdf2vfp.S",
"arm/eqsf2vfp.S",
"arm/extendsfdf2vfp.S",
"arm/fixdfsivfp.S",
"arm/fixsfsivfp.S",
"arm/fixunsdfsivfp.S",
"arm/fixunssfsivfp.S",
"arm/floatsidfvfp.S",
"arm/floatsisfvfp.S",
"arm/floatunssidfvfp.S",
"arm/floatunssisfvfp.S",
"arm/gedf2vfp.S",
"arm/gesf2vfp.S",
"arm/gtdf2vfp.S",
"arm/gtsf2vfp.S",
"arm/ledf2vfp.S",
"arm/lesf2vfp.S",
"arm/ltdf2vfp.S",
"arm/ltsf2vfp.S",
"arm/muldf3vfp.S",
"arm/mulsf3vfp.S",
"arm/negdf2vfp.S",
"arm/negsf2vfp.S",
"arm/nedf2vfp.S",
"arm/nesf2vfp.S",
"arm/restore_vfp_d8_d15_regs.S",
"arm/save_vfp_d8_d15_regs.S",
"arm/subdf3vfp.S",
"arm/subsf3vfp.S",
"arm/truncdfsf2vfp.S",
"arm/unorddf2vfp.S",
"arm/unordsf2vfp.S"]);
}
if target.contains("aarch64") {
sources.extend(&["comparetf2.c",
"extenddftf2.c",
"extendsftf2.c",
"fixtfdi.c",
"fixtfsi.c",
"fixtfti.c",
"fixunstfdi.c",
"fixunstfsi.c",
"fixunstfti.c",
"floatditf.c",
"floatsitf.c",
"floatunditf.c",
"floatunsitf.c",
"multc3.c",
"trunctfdf2.c",
"trunctfsf2.c"]);
}
for src in sources.map.values() {
cfg.file(Path::new("../compiler-rt/lib/builtins").join(src));
}
cfg.compile("libcompiler-rt.a");
}

View file

@ -0,0 +1,19 @@
// 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.
#![cfg_attr(not(stage0), feature(compiler_builtins))]
#![no_std]
#![cfg_attr(not(stage0), compiler_builtins)]
#![unstable(feature = "compiler_builtins_lib",
reason = "internal implementation detail of rustc right now",
issue = "0")]
#![crate_name = "compiler_builtins"]
#![crate_type = "rlib"]
#![feature(staged_api)]

View file

@ -317,6 +317,7 @@ impl<T:Copy> Clone for Cell<T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T:Default + Copy> Default for Cell<T> {
/// Creates a `Cell<T>`, with the `Default` value for T.
#[inline]
fn default() -> Cell<T> {
Cell::new(Default::default())
@ -758,6 +759,7 @@ impl<T: Clone> Clone for RefCell<T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T:Default> Default for RefCell<T> {
/// Creates a `RefCell<T>`, with the `Default` value for T.
#[inline]
fn default() -> RefCell<T> {
RefCell::new(Default::default())
@ -1139,6 +1141,7 @@ impl<T: ?Sized> UnsafeCell<T> {
#[stable(feature = "unsafe_cell_default", since = "1.9.0")]
impl<T: Default> Default for UnsafeCell<T> {
/// Creates an `UnsafeCell`, with the `Default` value for T.
fn default() -> UnsafeCell<T> {
UnsafeCell::new(Default::default())
}

View file

@ -14,10 +14,14 @@
//! assign them or pass them as arguments, the receiver will get a copy,
//! leaving the original value in place. These types do not require
//! allocation to copy and do not have finalizers (i.e. they do not
//! contain owned boxes or implement `Drop`), so the compiler considers
//! contain owned boxes or implement [`Drop`]), so the compiler considers
//! them cheap and safe to copy. For other types copies must be made
//! explicitly, by convention implementing the `Clone` trait and calling
//! the `clone` method.
//! explicitly, by convention implementing the [`Clone`] trait and calling
//! the [`clone`][clone] method.
//!
//! [`Clone`]: trait.Clone.html
//! [clone]: trait.Clone.html#tymethod.clone
//! [`Drop`]: ../../std/ops/trait.Drop.html
//!
//! Basic usage example:
//!
@ -46,22 +50,22 @@
/// A common trait for the ability to explicitly duplicate an object.
///
/// Differs from `Copy` in that `Copy` is implicit and extremely inexpensive, while
/// Differs from [`Copy`] in that [`Copy`] is implicit and extremely inexpensive, while
/// `Clone` is always explicit and may or may not be expensive. In order to enforce
/// these characteristics, Rust does not allow you to reimplement `Copy`, but you
/// these characteristics, Rust does not allow you to reimplement [`Copy`], but you
/// may reimplement `Clone` and run arbitrary code.
///
/// Since `Clone` is more general than `Copy`, you can automatically make anything
/// `Copy` be `Clone` as well.
/// Since `Clone` is more general than [`Copy`], you can automatically make anything
/// [`Copy`] be `Clone` as well.
///
/// ## Derivable
///
/// This trait can be used with `#[derive]` if all fields are `Clone`. The `derive`d
/// implementation of `clone()` calls `clone()` on each field.
/// implementation of [`clone()`] calls [`clone()`] on each field.
///
/// ## How can I implement `Clone`?
///
/// Types that are `Copy` should have a trivial implementation of `Clone`. More formally:
/// Types that are [`Copy`] should have a trivial implementation of `Clone`. More formally:
/// if `T: Copy`, `x: T`, and `y: &T`, then `let x = y.clone();` is equivalent to `let x = *y;`.
/// Manual implementations should be careful to uphold this invariant; however, unsafe code
/// must not rely on it to ensure memory safety.
@ -70,6 +74,9 @@
/// library only implements `Clone` up until arrays of size 32. In this case, the implementation of
/// `Clone` cannot be `derive`d, but can be implemented as:
///
/// [`Copy`]: ../../std/marker/trait.Copy.html
/// [`clone()`]: trait.Clone.html#tymethod.clone
///
/// ```
/// #[derive(Copy)]
/// struct Stats {
@ -106,10 +113,23 @@ pub trait Clone : Sized {
}
}
// FIXME(aburka): this method is used solely by #[derive] to
// assert that every component of a type implements Clone.
// FIXME(aburka): these structs are used solely by #[derive] to
// assert that every component of a type implements Clone or Copy.
//
// This should never be called by user code.
// These structs should never appear in user code.
#[doc(hidden)]
#[allow(missing_debug_implementations)]
#[unstable(feature = "derive_clone_copy",
reason = "deriving hack, should not be public",
issue = "0")]
pub struct AssertParamIsClone<T: Clone + ?Sized> { _field: ::marker::PhantomData<T> }
#[doc(hidden)]
#[allow(missing_debug_implementations)]
#[unstable(feature = "derive_clone_copy",
reason = "deriving hack, should not be public",
issue = "0")]
pub struct AssertParamIsCopy<T: Copy + ?Sized> { _field: ::marker::PhantomData<T> }
#[cfg(stage0)]
#[doc(hidden)]
#[inline(always)]
#[unstable(feature = "derive_clone_copy",

View file

@ -129,7 +129,7 @@ pub trait PartialEq<Rhs: ?Sized = Self> {
/// This trait can be used with `#[derive]`. When `derive`d, because `Eq` has
/// no extra methods, it is only informing the compiler that this is an
/// equivalence relation rather than a partial equivalence relation. Note that
/// the `derive` strategy requires all fields are `PartialEq`, which isn't
/// the `derive` strategy requires all fields are `Eq`, which isn't
/// always desired.
///
/// ## How can I implement `Eq`?
@ -165,6 +165,17 @@ pub trait Eq: PartialEq<Self> {
fn assert_receiver_is_total_eq(&self) {}
}
// FIXME: this struct is used solely by #[derive] to
// assert that every component of a type implements Eq.
//
// This struct should never appear in user code.
#[doc(hidden)]
#[allow(missing_debug_implementations)]
#[unstable(feature = "derive_eq",
reason = "deriving hack, should not be public",
issue = "0")]
pub struct AssertParamIsEq<T: Eq + ?Sized> { _field: ::marker::PhantomData<T> }
/// An `Ordering` is the result of a comparison between two values.
///
/// # Examples

View file

@ -92,6 +92,22 @@ pub trait AsRef<T: ?Sized> {
/// [`Option<T>`]: ../../std/option/enum.Option.html
/// [`Result<T, E>`]: ../../std/result/enum.Result.html
///
/// # Examples
///
/// [`Box<T>`] implements `AsMut<T>`:
///
/// [`Box<T>`]: ../../std/boxed/struct.Box.html
///
/// ```
/// fn add_one<T: AsMut<u64>>(num: &mut T) {
/// *num.as_mut() += 1;
/// }
///
/// let mut boxed_num = Box::new(0);
/// add_one(&mut boxed_num);
/// assert_eq!(*boxed_num, 1);
/// ```
///
/// # Generic Impls
///
/// - `AsMut` auto-dereferences if the inner type is a reference or a mutable

View file

@ -272,10 +272,14 @@ impl<'a> Arguments<'a> {
/// safely be done so, so no constructors are given and the fields are private
/// to prevent modification.
///
/// The `format_args!` macro will safely create an instance of this structure
/// The [`format_args!`] macro will safely create an instance of this structure
/// and pass it to a function or closure, passed as the first argument. The
/// macro validates the format string at compile-time so usage of the `write`
/// and `format` functions can be safely performed.
/// macro validates the format string at compile-time so usage of the [`write`]
/// and [`format`] functions can be safely performed.
///
/// [`format_args!`]: ../../std/macro.format_args.html
/// [`format`]: ../../std/fmt/fn.format.html
/// [`write`]: ../../std/fmt/fn.write.html
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Copy, Clone)]
pub struct Arguments<'a> {

View file

@ -333,6 +333,7 @@ impl<S: Sip> Clone for Hasher<S> {
}
impl<S: Sip> Default for Hasher<S> {
/// Creates a `Hasher<S>` with the two initial keys set to 0.
#[inline]
fn default() -> Hasher<S> {
Hasher::new_with_keys(0, 0)

View file

@ -194,6 +194,20 @@ extern "rust-intrinsic" {
/// own, or if it does not enable any significant optimizations.
pub fn assume(b: bool);
#[cfg(not(stage0))]
/// Hints to the compiler that branch condition is likely to be true.
/// Returns the value passed to it.
///
/// Any use other than with `if` statements will probably not have an effect.
pub fn likely(b: bool) -> bool;
#[cfg(not(stage0))]
/// Hints to the compiler that branch condition is likely to be false.
/// Returns the value passed to it.
///
/// Any use other than with `if` statements will probably not have an effect.
pub fn unlikely(b: bool) -> bool;
/// Executes a breakpoint trap, for inspection by a debugger.
pub fn breakpoint();
@ -262,22 +276,25 @@ extern "rust-intrinsic" {
/// Moves a value out of scope without running drop glue.
pub fn forget<T>(_: T) -> ();
/// Reinterprets the bits of a value of one type as another type; both types
/// must have the same size. Neither the original, nor the result, may be an
/// [invalid value] (../../nomicon/meet-safe-and-unsafe.html).
/// Reinterprets the bits of a value of one type as another type.
///
/// Both types must have the same size. Neither the original, nor the result,
/// may be an [invalid value](../../nomicon/meet-safe-and-unsafe.html).
///
/// `transmute` is semantically equivalent to a bitwise move of one type
/// into another. It copies the bits from the destination type into the
/// source type, then forgets the original. It's equivalent to C's `memcpy`
/// under the hood, just like `transmute_copy`.
/// into another. It copies the bits from the source value into the
/// destination value, then forgets the original. It's equivalent to C's
/// `memcpy` under the hood, just like `transmute_copy`.
///
/// `transmute` is incredibly unsafe. There are a vast number of ways to
/// cause undefined behavior with this function. `transmute` should be
/// `transmute` is **incredibly** unsafe. There are a vast number of ways to
/// cause [undefined behavior][ub] with this function. `transmute` should be
/// the absolute last resort.
///
/// The [nomicon](../../nomicon/transmutes.html) has additional
/// documentation.
///
/// [ub]: ../../reference.html#behavior-considered-undefined
///
/// # Examples
///
/// There are a few things that `transmute` is really useful for.
@ -292,7 +309,8 @@ extern "rust-intrinsic" {
/// assert_eq!(bitpattern, 0x3F800000);
/// ```
///
/// Turning a pointer into a function pointer:
/// Turning a pointer into a function pointer. This is *not* portable to
/// machines where function pointers and data pointers have different sizes.
///
/// ```
/// fn foo() -> i32 {
@ -305,8 +323,8 @@ extern "rust-intrinsic" {
/// assert_eq!(function(), 0);
/// ```
///
/// Extending a lifetime, or shortening an invariant lifetime; this is
/// advanced, very unsafe rust:
/// Extending a lifetime, or shortening an invariant lifetime. This is
/// advanced, very unsafe Rust!
///
/// ```
/// struct R<'a>(&'a i32);
@ -322,11 +340,9 @@ extern "rust-intrinsic" {
///
/// # Alternatives
///
/// However, many uses of `transmute` can be achieved through other means.
/// `transmute` can transform any type into any other, with just the caveat
/// that they're the same size, and often interesting results occur. Below
/// are common applications of `transmute` which can be replaced with safe
/// applications of `as`:
/// Don't despair: many uses of `transmute` can be achieved through other means.
/// Below are common applications of `transmute` which can be replaced with safer
/// constructs.
///
/// Turning a pointer into a `usize`:
///
@ -335,6 +351,7 @@ extern "rust-intrinsic" {
/// let ptr_num_transmute = unsafe {
/// std::mem::transmute::<&i32, usize>(ptr)
/// };
///
/// // Use an `as` cast instead
/// let ptr_num_cast = ptr as *const i32 as usize;
/// ```
@ -346,6 +363,7 @@ extern "rust-intrinsic" {
/// let ref_transmuted = unsafe {
/// std::mem::transmute::<*mut i32, &mut i32>(ptr)
/// };
///
/// // Use a reborrow instead
/// let ref_casted = unsafe { &mut *ptr };
/// ```
@ -357,6 +375,7 @@ extern "rust-intrinsic" {
/// let val_transmuted = unsafe {
/// std::mem::transmute::<&mut i32, &mut u32>(ptr)
/// };
///
/// // Now, put together `as` and reborrowing - note the chaining of `as`
/// // `as` is not transitive
/// let val_casts = unsafe { &mut *(ptr as *mut i32 as *mut u32) };
@ -368,9 +387,11 @@ extern "rust-intrinsic" {
/// // this is not a good way to do this.
/// let slice = unsafe { std::mem::transmute::<&str, &[u8]>("Rust") };
/// assert_eq!(slice, &[82, 117, 115, 116]);
///
/// // You could use `str::as_bytes`
/// let slice = "Rust".as_bytes();
/// assert_eq!(slice, &[82, 117, 115, 116]);
///
/// // Or, just use a byte string, if you have control over the string
/// // literal
/// assert_eq!(b"Rust", &[82, 117, 115, 116]);
@ -381,18 +402,21 @@ extern "rust-intrinsic" {
/// ```
/// let store = [0, 1, 2, 3];
/// let mut v_orig = store.iter().collect::<Vec<&i32>>();
///
/// // Using transmute: this is Undefined Behavior, and a bad idea.
/// // However, it is no-copy.
/// let v_transmuted = unsafe {
/// std::mem::transmute::<Vec<&i32>, Vec<Option<&i32>>>(
/// v_orig.clone())
/// };
///
/// // This is the suggested, safe way.
/// // It does copy the entire Vector, though, into a new array.
/// // It does copy the entire vector, though, into a new array.
/// let v_collected = v_orig.clone()
/// .into_iter()
/// .map(|r| Some(r))
/// .collect::<Vec<Option<&i32>>>();
///
/// // The no-copy, unsafe way, still using transmute, but not UB.
/// // This is equivalent to the original, but safer, and reuses the
/// // same Vec internals. Therefore the new inner type must have the
@ -412,6 +436,7 @@ extern "rust-intrinsic" {
///
/// ```
/// use std::{slice, mem};
///
/// // There are multiple ways to do this; and there are multiple problems
/// // with the following, transmute, way.
/// fn split_at_mut_transmute<T>(slice: &mut [T], mid: usize)
@ -426,6 +451,7 @@ extern "rust-intrinsic" {
/// (&mut slice[0..mid], &mut slice2[mid..len])
/// }
/// }
///
/// // This gets rid of the typesafety problems; `&mut *` will *only* give
/// // you an `&mut T` from an `&mut T` or `*mut T`.
/// fn split_at_mut_casts<T>(slice: &mut [T], mid: usize)
@ -439,6 +465,7 @@ extern "rust-intrinsic" {
/// (&mut slice[0..mid], &mut slice2[mid..len])
/// }
/// }
///
/// // This is how the standard library does it. This is the best method, if
/// // you need to do something like this
/// fn split_at_stdlib<T>(slice: &mut [T], mid: usize)

View file

@ -1657,6 +1657,32 @@ pub trait Iterator {
.map(|(_, x)| x)
}
/// Returns the element that gives the maximum value with respect to the
/// specified comparison function.
///
/// Returns the rightmost element if the comparison determines two elements
/// to be equally maximum.
///
/// # Examples
///
/// ```
/// #![feature(iter_max_by)]
/// let a = [-3_i32, 0, 1, 5, -10];
/// assert_eq!(*a.iter().max_by(|x, y| x.cmp(y)).unwrap(), 5);
/// ```
#[inline]
#[unstable(feature = "iter_max_by", issue="36105")]
fn max_by<F>(self, mut compare: F) -> Option<Self::Item>
where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering,
{
select_fold1(self,
|_| (),
// switch to y even if it is only equal, to preserve
// stability.
|_, x, _, y| Ordering::Greater != compare(x, y))
.map(|(_, x)| x)
}
/// Returns the element that gives the minimum value from the
/// specified function.
///
@ -1681,6 +1707,33 @@ pub trait Iterator {
.map(|(_, x)| x)
}
/// Returns the element that gives the minimum value with respect to the
/// specified comparison function.
///
/// Returns the latest element if the comparison determines two elements
/// to be equally minimum.
///
/// # Examples
///
/// ```
/// #![feature(iter_min_by)]
/// let a = [-3_i32, 0, 1, 5, -10];
/// assert_eq!(*a.iter().min_by(|x, y| x.cmp(y)).unwrap(), -10);
/// ```
#[inline]
#[unstable(feature = "iter_min_by", issue="36105")]
fn min_by<F>(self, mut compare: F) -> Option<Self::Item>
where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering,
{
select_fold1(self,
|_| (),
// switch to y even if it is strictly smaller, to
// preserve stability.
|_, x, _, y| Ordering::Greater == compare(x, y))
.map(|(_, x)| x)
}
/// Reverses an iterator's direction.
///
/// Usually, iterators iterate from left to right. After using `rev()`,
@ -1814,7 +1867,8 @@ pub trait Iterator {
/// # Panics
///
/// When calling `sum` and a primitive integer type is being returned, this
/// method will panic if the computation overflows.
/// method will panic if the computation overflows and debug assertions are
/// enabled.
///
/// # Examples
///
@ -1841,7 +1895,8 @@ pub trait Iterator {
/// # Panics
///
/// When calling `product` and a primitive integer type is being returned,
/// this method will panic if the computation overflows.
/// method will panic if the computation overflows and debug assertions are
/// enabled.
///
/// # Examples
///

View file

@ -643,7 +643,9 @@ impl<A, B> FusedIterator for Chain<A, B>
pub struct Zip<A, B> {
a: A,
b: B,
spec: <(A, B) as ZipImplData>::Data,
// index and len are only used by the specialized version of zip
index: usize,
len: usize,
}
#[stable(feature = "rust1", since = "1.0.0")]
@ -685,17 +687,6 @@ trait ZipImpl<A, B> {
B: DoubleEndedIterator + ExactSizeIterator;
}
// Zip specialization data members
#[doc(hidden)]
trait ZipImplData {
type Data: 'static + Clone + Default + fmt::Debug;
}
#[doc(hidden)]
impl<T> ZipImplData for T {
default type Data = ();
}
// General Zip impl
#[doc(hidden)]
impl<A, B> ZipImpl<A, B> for Zip<A, B>
@ -706,7 +697,8 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B>
Zip {
a: a,
b: b,
spec: Default::default(), // unused
index: 0, // unused
len: 0, // unused
}
}
@ -759,20 +751,6 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B>
}
}
#[doc(hidden)]
#[derive(Default, Debug, Clone)]
struct ZipImplFields {
index: usize,
len: usize,
}
#[doc(hidden)]
impl<A, B> ZipImplData for (A, B)
where A: TrustedRandomAccess, B: TrustedRandomAccess
{
type Data = ZipImplFields;
}
#[doc(hidden)]
impl<A, B> ZipImpl<A, B> for Zip<A, B>
where A: TrustedRandomAccess, B: TrustedRandomAccess
@ -782,18 +760,16 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B>
Zip {
a: a,
b: b,
spec: ZipImplFields {
index: 0,
len: len,
}
index: 0,
len: len,
}
}
#[inline]
fn next(&mut self) -> Option<(A::Item, B::Item)> {
if self.spec.index < self.spec.len {
let i = self.spec.index;
self.spec.index += 1;
if self.index < self.len {
let i = self.index;
self.index += 1;
unsafe {
Some((self.a.get_unchecked(i), self.b.get_unchecked(i)))
}
@ -804,7 +780,7 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B>
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.spec.len - self.spec.index;
let len = self.len - self.index;
(len, Some(len))
}
@ -813,9 +789,9 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B>
where A: DoubleEndedIterator + ExactSizeIterator,
B: DoubleEndedIterator + ExactSizeIterator
{
if self.spec.index < self.spec.len {
self.spec.len -= 1;
let i = self.spec.len;
if self.index < self.len {
self.len -= 1;
let i = self.len;
unsafe {
Some((self.a.get_unchecked(i), self.b.get_unchecked(i)))
}

View file

@ -7,6 +7,7 @@
// <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 ops::{Mul, Add};
/// Conversion from an `Iterator`.
///
@ -581,41 +582,34 @@ pub trait Product<A = Self>: Sized {
fn product<I: Iterator<Item=A>>(iter: I) -> Self;
}
// NB: explicitly use Add and Mul here to inherit overflow checks
macro_rules! integer_sum_product {
($($a:ident)*) => ($(
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
impl Sum for $a {
fn sum<I: Iterator<Item=$a>>(iter: I) -> $a {
iter.fold(0, |a, b| {
a.checked_add(b).expect("overflow in sum")
})
iter.fold(0, Add::add)
}
}
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
impl Product for $a {
fn product<I: Iterator<Item=$a>>(iter: I) -> $a {
iter.fold(1, |a, b| {
a.checked_mul(b).expect("overflow in product")
})
iter.fold(1, Mul::mul)
}
}
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
impl<'a> Sum<&'a $a> for $a {
fn sum<I: Iterator<Item=&'a $a>>(iter: I) -> $a {
iter.fold(0, |a, b| {
a.checked_add(*b).expect("overflow in sum")
})
iter.cloned().fold(0, Add::add)
}
}
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
impl<'a> Product<&'a $a> for $a {
fn product<I: Iterator<Item=&'a $a>>(iter: I) -> $a {
iter.fold(1, |a, b| {
a.checked_mul(*b).expect("overflow in product")
})
iter.cloned().fold(1, Mul::mul)
}
}
)*)

View file

@ -119,6 +119,44 @@ macro_rules! assert_eq {
});
}
/// Asserts that two expressions are not equal to each other.
///
/// On panic, this macro will print the values of the expressions with their
/// debug representations.
///
/// # Examples
///
/// ```
/// let a = 3;
/// let b = 2;
/// assert_ne!(a, b);
/// ```
#[macro_export]
#[stable(feature = "assert_ne", since = "1.12.0")]
macro_rules! assert_ne {
($left:expr , $right:expr) => ({
match (&$left, &$right) {
(left_val, right_val) => {
if *left_val == *right_val {
panic!("assertion failed: `(left != right)` \
(left: `{:?}`, right: `{:?}`)", left_val, right_val)
}
}
}
});
($left:expr , $right:expr, $($arg:tt)*) => ({
match (&($left), &($right)) {
(left_val, right_val) => {
if *left_val == *right_val {
panic!("assertion failed: `(left != right)` \
(left: `{:?}`, right: `{:?}`): {}", left_val, right_val,
format_args!($($arg)*))
}
}
}
});
}
/// Ensure that a boolean expression is `true` at runtime.
///
/// This will invoke the `panic!` macro if the provided expression cannot be
@ -189,10 +227,44 @@ macro_rules! debug_assert_eq {
($($arg:tt)*) => (if cfg!(debug_assertions) { assert_eq!($($arg)*); })
}
/// Helper macro for unwrapping `Result` values while returning early with an
/// error if the value of the expression is `Err`. Can only be used in
/// functions that return `Result` because of the early return of `Err` that
/// it provides.
/// Asserts that two expressions are not equal to each other.
///
/// On panic, this macro will print the values of the expressions with their
/// debug representations.
///
/// Unlike `assert_ne!`, `debug_assert_ne!` statements are only enabled in non
/// optimized builds by default. An optimized build will omit all
/// `debug_assert_ne!` statements unless `-C debug-assertions` is passed to the
/// compiler. This makes `debug_assert_ne!` useful for checks that are too
/// expensive to be present in a release build but may be helpful during
/// development.
///
/// # Examples
///
/// ```
/// let a = 3;
/// let b = 2;
/// debug_assert_ne!(a, b);
/// ```
#[macro_export]
#[stable(feature = "assert_ne", since = "1.12.0")]
macro_rules! debug_assert_ne {
($($arg:tt)*) => (if cfg!(debug_assertions) { assert_ne!($($arg)*); })
}
/// Helper macro for reducing boilerplate code for matching `Result` together
/// with converting downstream errors.
///
/// `try!` matches the given `Result`. In case of the `Ok` variant, the
/// expression has the value of the wrapped value.
///
/// In case of the `Err` variant, it retrieves the inner error. `try!` then
/// performs conversion using `From`. This provides automatic conversion
/// between specialized errors and more general ones. The resulting
/// error is then immediately returned.
///
/// Because of the early return, `try!` can only be used in functions that
/// return `Result`.
///
/// # Examples
///
@ -201,18 +273,28 @@ macro_rules! debug_assert_eq {
/// use std::fs::File;
/// use std::io::prelude::*;
///
/// fn write_to_file_using_try() -> Result<(), io::Error> {
/// enum MyError {
/// FileWriteError
/// }
///
/// impl From<io::Error> for MyError {
/// fn from(e: io::Error) -> MyError {
/// MyError::FileWriteError
/// }
/// }
///
/// fn write_to_file_using_try() -> Result<(), MyError> {
/// let mut file = try!(File::create("my_best_friends.txt"));
/// try!(file.write_all(b"This is a list of my best friends."));
/// println!("I wrote to the file");
/// Ok(())
/// }
/// // This is equivalent to:
/// fn write_to_file_using_match() -> Result<(), io::Error> {
/// fn write_to_file_using_match() -> Result<(), MyError> {
/// let mut file = try!(File::create("my_best_friends.txt"));
/// match file.write_all(b"This is a list of my best friends.") {
/// Ok(v) => v,
/// Err(e) => return Err(e),
/// Err(e) => return Err(From::from(e)),
/// }
/// println!("I wrote to the file");
/// Ok(())

View file

@ -8,11 +8,11 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! Primitive traits and marker types representing basic 'kinds' of types.
//! Primitive traits and types representing basic properties of types.
//!
//! Rust types can be classified in various useful ways according to
//! intrinsic properties of the type. These classifications, often called
//! 'kinds', are represented as traits.
//! their intrinsic properties. These classifications are represented
//! as traits.
#![stable(feature = "rust1", since = "1.0.0")]
@ -22,7 +22,21 @@ use hash::Hasher;
/// Types that can be transferred across thread boundaries.
///
/// This trait is automatically derived when the compiler determines it's appropriate.
/// This trait is automatically implemented when the compiler determines it's
/// appropriate.
///
/// An example of a non-`Send` type is the reference-counting pointer
/// [`rc::Rc`][rc]. If two threads attempt to clone `Rc`s that point to the same
/// reference-counted value, they might try to update the reference count at the
/// same time, which is [undefined behavior][ub] because `Rc` doesn't use atomic
/// operations. Its cousin [`sync::Arc`][arc] does use atomic operations (incurring
/// some overhead) and thus is `Send`.
///
/// See [the Nomicon](../../nomicon/send-and-sync.html) for more details.
///
/// [rc]: ../../std/rc/struct.Rc.html
/// [arc]: ../../std/sync/struct.Arc.html
/// [ub]: ../../reference.html#behavior-considered-undefined
#[stable(feature = "rust1", since = "1.0.0")]
#[lang = "send"]
#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
@ -38,10 +52,10 @@ impl<T: ?Sized> !Send for *const T { }
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> !Send for *mut T { }
/// Types with a constant size known at compile-time.
/// Types with a constant size known at compile time.
///
/// All type parameters which can be bounded have an implicit bound of `Sized`. The special syntax
/// `?Sized` can be used to remove this bound if it is not appropriate.
/// All type parameters have an implicit bound of `Sized`. The special syntax
/// `?Sized` can be used to remove this bound if it's not appropriate.
///
/// ```
/// # #![allow(dead_code)]
@ -51,6 +65,26 @@ impl<T: ?Sized> !Send for *mut T { }
/// // struct FooUse(Foo<[i32]>); // error: Sized is not implemented for [i32]
/// struct BarUse(Bar<[i32]>); // OK
/// ```
///
/// The one exception is the implicit `Self` type of a trait, which does not
/// get an implicit `Sized` bound. This is because a `Sized` bound prevents
/// the trait from being used to form a [trait object]:
///
/// ```
/// # #![allow(unused_variables)]
/// trait Foo { }
/// trait Bar: Sized { }
///
/// struct Impl;
/// impl Foo for Impl { }
/// impl Bar for Impl { }
///
/// let x: &Foo = &Impl; // OK
/// // let y: &Bar = &Impl; // error: the trait `Bar` cannot
/// // be made into an object
/// ```
///
/// [trait object]: ../../book/trait-objects.html
#[stable(feature = "rust1", since = "1.0.0")]
#[lang = "sized"]
#[rustc_on_unimplemented = "`{Self}` does not have a constant size known at compile-time"]
@ -59,14 +93,27 @@ pub trait Sized {
// Empty.
}
/// Types that can be "unsized" to a dynamically sized type.
/// Types that can be "unsized" to a dynamically-sized type.
///
/// For example, the sized array type `[i8; 2]` implements `Unsize<[i8]>` and
/// `Unsize<fmt::Debug>`.
///
/// All implementations of `Unsize` are provided automatically by the compiler.
///
/// `Unsize` is used along with [`ops::CoerceUnsized`][coerceunsized] to allow
/// "user-defined" containers such as [`rc::Rc`][rc] to contain dynamically-sized
/// types. See the [DST coercion RFC][RFC982] for more details.
///
/// [coerceunsized]: ../ops/trait.CoerceUnsized.html
/// [rc]: ../../std/rc/struct.Rc.html
/// [RFC982]: https://github.com/rust-lang/rfcs/blob/master/text/0982-dst-coercion.md
#[unstable(feature = "unsize", issue = "27732")]
#[lang="unsize"]
pub trait Unsize<T: ?Sized> {
// Empty.
}
/// Types that can be copied by simply copying bits (i.e. `memcpy`).
/// Types whose values can be duplicated simply by copying bits.
///
/// By default, variable bindings have 'move semantics.' In other
/// words:
@ -87,7 +134,8 @@ pub trait Unsize<T: ?Sized> {
/// However, if a type implements `Copy`, it instead has 'copy semantics':
///
/// ```
/// // we can just derive a `Copy` implementation
/// // We can derive a `Copy` implementation. `Clone` is also required, as it's
/// // a supertrait of `Copy`.
/// #[derive(Debug, Copy, Clone)]
/// struct Foo;
///
@ -100,13 +148,59 @@ pub trait Unsize<T: ?Sized> {
/// println!("{:?}", x); // A-OK!
/// ```
///
/// It's important to note that in these two examples, the only difference is if you are allowed to
/// access `x` after the assignment: a move is also a bitwise copy under the hood.
/// It's important to note that in these two examples, the only difference is whether you
/// are allowed to access `x` after the assignment. Under the hood, both a copy and a move
/// can result in bits being copied in memory, although this is sometimes optimized away.
///
/// ## How can I implement `Copy`?
///
/// There are two ways to implement `Copy` on your type. The simplest is to use `derive`:
///
/// ```
/// #[derive(Copy, Clone)]
/// struct MyStruct;
/// ```
///
/// You can also implement `Copy` and `Clone` manually:
///
/// ```
/// struct MyStruct;
///
/// impl Copy for MyStruct { }
///
/// impl Clone for MyStruct {
/// fn clone(&self) -> MyStruct {
/// *self
/// }
/// }
/// ```
///
/// There is a small difference between the two: the `derive` strategy will also place a `Copy`
/// bound on type parameters, which isn't always desired.
///
/// ## What's the difference between `Copy` and `Clone`?
///
/// Copies happen implicitly, for example as part of an assignment `y = x`. The behavior of
/// `Copy` is not overloadable; it is always a simple bit-wise copy.
///
/// Cloning is an explicit action, `x.clone()`. The implementation of [`Clone`][clone] can
/// provide any type-specific behavior necessary to duplicate values safely. For example,
/// the implementation of `Clone` for [`String`][string] needs to copy the pointed-to string
/// buffer in the heap. A simple bitwise copy of `String` values would merely copy the
/// pointer, leading to a double free down the line. For this reason, `String` is `Clone`
/// but not `Copy`.
///
/// `Clone` is a supertrait of `Copy`, so everything which is `Copy` must also implement
/// `Clone`. If a type is `Copy` then its `Clone` implementation need only return `*self`
/// (see the example above).
///
/// [clone]: ../clone/trait.Clone.html
/// [string]: ../../std/string/struct.String.html
///
/// ## When can my type be `Copy`?
///
/// A type can implement `Copy` if all of its components implement `Copy`. For example, this
/// `struct` can be `Copy`:
/// struct can be `Copy`:
///
/// ```
/// # #[allow(dead_code)]
@ -116,7 +210,8 @@ pub trait Unsize<T: ?Sized> {
/// }
/// ```
///
/// A `struct` can be `Copy`, and `i32` is `Copy`, so therefore, `Point` is eligible to be `Copy`.
/// A struct can be `Copy`, and `i32` is `Copy`, therefore `Point` is eligible to be `Copy`.
/// By contrast, consider
///
/// ```
/// # #![allow(dead_code)]
@ -126,107 +221,114 @@ pub trait Unsize<T: ?Sized> {
/// }
/// ```
///
/// The `PointList` `struct` cannot implement `Copy`, because `Vec<T>` is not `Copy`. If we
/// The struct `PointList` cannot implement `Copy`, because [`Vec<T>`] is not `Copy`. If we
/// attempt to derive a `Copy` implementation, we'll get an error:
///
/// ```text
/// the trait `Copy` may not be implemented for this type; field `points` does not implement `Copy`
/// ```
///
/// ## When can my type _not_ be `Copy`?
/// ## When *can't* my type be `Copy`?
///
/// Some types can't be copied safely. For example, copying `&mut T` would create an aliased
/// mutable reference, and copying `String` would result in two attempts to free the same buffer.
/// mutable reference. Copying [`String`] would duplicate responsibility for managing the `String`'s
/// buffer, leading to a double free.
///
/// Generalizing the latter case, any type implementing `Drop` can't be `Copy`, because it's
/// managing some resource besides its own `size_of::<T>()` bytes.
/// Generalizing the latter case, any type implementing [`Drop`] can't be `Copy`, because it's
/// managing some resource besides its own [`size_of::<T>()`] bytes.
///
/// ## What if I derive `Copy` on a type that can't?
/// If you try to implement `Copy` on a struct or enum containing non-`Copy` data, you will get a
/// compile-time error. Specifically, with structs you'll get [E0204] and with enums you'll get
/// [E0205].
///
/// If you try to derive `Copy` on a struct or enum, you will get a compile-time error.
/// Specifically, with structs you'll get [E0204](https://doc.rust-lang.org/error-index.html#E0204)
/// and with enums you'll get [E0205](https://doc.rust-lang.org/error-index.html#E0205).
/// [E0204]: https://doc.rust-lang.org/error-index.html#E0204
/// [E0205]: https://doc.rust-lang.org/error-index.html#E0205
///
/// ## When should my type be `Copy`?
/// ## When *should* my type be `Copy`?
///
/// Generally speaking, if your type _can_ implement `Copy`, it should. There's one important thing
/// to consider though: if you think your type may _not_ be able to implement `Copy` in the future,
/// then it might be prudent to not implement `Copy`. This is because removing `Copy` is a breaking
/// change: that second example would fail to compile if we made `Foo` non-`Copy`.
/// Generally speaking, if your type _can_ implement `Copy`, it should. Keep in mind, though,
/// that implementing `Copy` is part of the public API of your type. If the type might become
/// non-`Copy` in the future, it could be prudent to omit the `Copy` implementation now, to
/// avoid a breaking API change.
///
/// ## Derivable
///
/// This trait can be used with `#[derive]` if all of its components implement `Copy` and the type
/// implements `Clone`. The implementation will copy the bytes of each field using `memcpy`.
///
/// ## How can I implement `Copy`?
///
/// There are two ways to implement `Copy` on your type:
///
/// ```
/// #[derive(Copy, Clone)]
/// struct MyStruct;
/// ```
///
/// and
///
/// ```
/// struct MyStruct;
/// impl Copy for MyStruct {}
/// impl Clone for MyStruct { fn clone(&self) -> MyStruct { *self } }
/// ```
///
/// There is a small difference between the two: the `derive` strategy will also place a `Copy`
/// bound on type parameters, which isn't always desired.
/// [`Vec<T>`]: ../../std/vec/struct.Vec.html
/// [`String`]: ../../std/string/struct.String.html
/// [`Drop`]: ../../std/ops/trait.Drop.html
/// [`size_of::<T>()`]: ../../std/mem/fn.size_of.html
#[stable(feature = "rust1", since = "1.0.0")]
#[lang = "copy"]
pub trait Copy : Clone {
// Empty.
}
/// Types that can be safely shared between threads when aliased.
/// Types for which it is safe to share references between threads.
///
/// This trait is automatically implemented when the compiler determines
/// it's appropriate.
///
/// The precise definition is: a type `T` is `Sync` if `&T` is
/// thread-safe. In other words, there is no possibility of data races
/// when passing `&T` references between threads.
/// [`Send`][send]. In other words, if there is no possibility of
/// [undefined behavior][ub] (including data races) when passing
/// `&T` references between threads.
///
/// As one would expect, primitive types like `u8` and `f64` are all
/// `Sync`, and so are simple aggregate types containing them (like
/// tuples, structs and enums). More instances of basic `Sync` types
/// include "immutable" types like `&T` and those with simple
/// inherited mutability, such as `Box<T>`, `Vec<T>` and most other
/// collection types. (Generic parameters need to be `Sync` for their
/// container to be `Sync`.)
/// As one would expect, primitive types like [`u8`][u8] and [`f64`][f64]
/// are all `Sync`, and so are simple aggregate types containing them,
/// like tuples, structs and enums. More examples of basic `Sync`
/// types include "immutable" types like `&T`, and those with simple
/// inherited mutability, such as [`Box<T>`][box], [`Vec<T>`][vec] and
/// most other collection types. (Generic parameters need to be `Sync`
/// for their container to be `Sync`.)
///
/// A somewhat surprising consequence of the definition is `&mut T` is
/// `Sync` (if `T` is `Sync`) even though it seems that it might
/// provide unsynchronized mutation. The trick is a mutable reference
/// stored in an aliasable reference (that is, `& &mut T`) becomes
/// read-only, as if it were a `& &T`, hence there is no risk of a data
/// race.
/// A somewhat surprising consequence of the definition is that `&mut T`
/// is `Sync` (if `T` is `Sync`) even though it seems like that might
/// provide unsynchronized mutation. The trick is that a mutable
/// reference behind a shared reference (that is, `& &mut T`)
/// becomes read-only, as if it were a `& &T`. Hence there is no risk
/// of a data race.
///
/// Types that are not `Sync` are those that have "interior
/// mutability" in a non-thread-safe way, such as `Cell` and `RefCell`
/// in `std::cell`. These types allow for mutation of their contents
/// even when in an immutable, aliasable slot, e.g. the contents of
/// `&Cell<T>` can be `.set`, and do not ensure data races are
/// impossible, hence they cannot be `Sync`. A higher level example
/// of a non-`Sync` type is the reference counted pointer
/// `std::rc::Rc`, because any reference `&Rc<T>` can clone a new
/// reference, which modifies the reference counts in a non-atomic
/// way.
/// mutability" in a non-thread-safe form, such as [`cell::Cell`][cell]
/// and [`cell::RefCell`][refcell]. These types allow for mutation of
/// their contents even through an immutable, shared reference. For
/// example the `set` method on `Cell<T>` takes `&self`, so it requires
/// only a shared reference `&Cell<T>`. The method performs no
/// synchronization, thus `Cell` cannot be `Sync`.
///
/// Another example of a non-`Sync` type is the reference-counting
/// pointer [`rc::Rc`][rc]. Given any reference `&Rc<T>`, you can clone
/// a new `Rc<T>`, modifying the reference counts in a non-atomic way.
///
/// For cases when one does need thread-safe interior mutability,
/// types like the atomics in `std::sync` and `Mutex` & `RWLock` in
/// the `sync` crate do ensure that any mutation cannot cause data
/// races. Hence these types are `Sync`.
/// Rust provides [atomic data types], as well as explicit locking via
/// [`sync::Mutex`][mutex] and [`sync::RWLock`][rwlock]. These types
/// ensure that any mutation cannot cause data races, hence the types
/// are `Sync`. Likewise, [`sync::Arc`][arc] provides a thread-safe
/// analogue of `Rc`.
///
/// Any types with interior mutability must also use the `std::cell::UnsafeCell`
/// wrapper around the value(s) which can be mutated when behind a `&`
/// reference; not doing this is undefined behavior (for example,
/// `transmute`-ing from `&T` to `&mut T` is invalid).
/// Any types with interior mutability must also use the
/// [`cell::UnsafeCell`][unsafecell] wrapper around the value(s) which
/// can be mutated through a shared reference. Failing to doing this is
/// [undefined behavior][ub]. For example, [`transmute`][transmute]-ing
/// from `&T` to `&mut T` is invalid.
///
/// This trait is automatically derived when the compiler determines it's appropriate.
/// See [the Nomicon](../../nomicon/send-and-sync.html) for more
/// details about `Sync`.
///
/// [send]: trait.Send.html
/// [u8]: ../../std/primitive.u8.html
/// [f64]: ../../std/primitive.f64.html
/// [box]: ../../std/boxed/struct.Box.html
/// [vec]: ../../std/vec/struct.Vec.html
/// [cell]: ../cell/struct.Cell.html
/// [refcell]: ../cell/struct.RefCell.html
/// [rc]: ../../std/rc/struct.Rc.html
/// [arc]: ../../std/sync/struct.Arc.html
/// [atomic data types]: ../sync/atomic/index.html
/// [mutex]: ../../std/sync/struct.Mutex.html
/// [rwlock]: ../../std/sync/struct.RwLock.html
/// [unsafecell]: ../cell/struct.UnsafeCell.html
/// [ub]: ../../reference.html#behavior-considered-undefined
/// [transmute]: ../../std/mem/fn.transmute.html
#[stable(feature = "rust1", since = "1.0.0")]
#[lang = "sync"]
#[rustc_on_unimplemented = "`{Self}` cannot be shared between threads safely"]
@ -295,29 +397,30 @@ macro_rules! impls{
)
}
/// `PhantomData<T>` allows you to describe that a type acts as if it stores a value of type `T`,
/// even though it does not. This allows you to inform the compiler about certain safety properties
/// of your code.
/// Zero-sized type used to mark things that "act like" they own a `T`.
///
/// For a more in-depth explanation of how to use `PhantomData<T>`, please see [the Nomicon].
/// Adding a `PhantomData<T>` field to your type tells the compiler that your
/// type acts as though it stores a value of type `T`, even though it doesn't
/// really. This information is used when computing certain safety properties.
///
/// [the Nomicon]: ../../nomicon/phantom-data.html
/// For a more in-depth explanation of how to use `PhantomData<T>`, please see
/// [the Nomicon](../../nomicon/phantom-data.html).
///
/// # A ghastly note 👻👻👻
///
/// Though they both have scary names, `PhantomData<T>` and 'phantom types' are related, but not
/// identical. Phantom types are a more general concept that don't require `PhantomData<T>` to
/// implement, but `PhantomData<T>` is the most common way to implement them in a correct manner.
/// Though they both have scary names, `PhantomData` and 'phantom types' are
/// related, but not identical. A phantom type parameter is simply a type
/// parameter which is never used. In Rust, this often causes the compiler to
/// complain, and the solution is to add a "dummy" use by way of `PhantomData`.
///
/// # Examples
///
/// ## Unused lifetime parameter
/// ## Unused lifetime parameters
///
/// Perhaps the most common time that `PhantomData` is required is
/// with a struct that has an unused lifetime parameter, typically as
/// part of some unsafe code. For example, here is a struct `Slice`
/// that has two pointers of type `*const T`, presumably pointing into
/// an array somewhere:
/// Perhaps the most common use case for `PhantomData` is a struct that has an
/// unused lifetime parameter, typically as part of some unsafe code. For
/// example, here is a struct `Slice` that has two pointers of type `*const T`,
/// presumably pointing into an array somewhere:
///
/// ```ignore
/// struct Slice<'a, T> {
@ -331,7 +434,7 @@ macro_rules! impls{
/// intent is not expressed in the code, since there are no uses of
/// the lifetime `'a` and hence it is not clear what data it applies
/// to. We can correct this by telling the compiler to act *as if* the
/// `Slice` struct contained a borrowed reference `&'a T`:
/// `Slice` struct contained a reference `&'a T`:
///
/// ```
/// use std::marker::PhantomData;
@ -340,29 +443,53 @@ macro_rules! impls{
/// struct Slice<'a, T: 'a> {
/// start: *const T,
/// end: *const T,
/// phantom: PhantomData<&'a T>
/// phantom: PhantomData<&'a T>,
/// }
/// ```
///
/// This also in turn requires that we annotate `T:'a`, indicating
/// that `T` is a type that can be borrowed for the lifetime `'a`.
/// This also in turn requires the annotation `T: 'a`, indicating
/// that any references in `T` are valid over the lifetime `'a`.
///
/// ## Unused type parameters
///
/// It sometimes happens that there are unused type parameters that
/// indicate what type of data a struct is "tied" to, even though that
/// data is not actually found in the struct itself. Here is an
/// example where this arises when handling external resources over a
/// foreign function interface. `PhantomData<T>` can prevent
/// mismatches by enforcing types in the method implementations:
/// When initializing a `Slice` you simply provide the value
/// `PhantomData` for the field `phantom`:
///
/// ```
/// # #![allow(dead_code)]
/// # trait ResType { fn foo(&self); }
/// # use std::marker::PhantomData;
/// # struct Slice<'a, T: 'a> {
/// # start: *const T,
/// # end: *const T,
/// # phantom: PhantomData<&'a T>,
/// # }
/// fn borrow_vec<'a, T>(vec: &'a Vec<T>) -> Slice<'a, T> {
/// let ptr = vec.as_ptr();
/// Slice {
/// start: ptr,
/// end: unsafe { ptr.offset(vec.len() as isize) },
/// phantom: PhantomData,
/// }
/// }
/// ```
///
/// ## Unused type parameters
///
/// It sometimes happens that you have unused type parameters which
/// indicate what type of data a struct is "tied" to, even though that
/// data is not actually found in the struct itself. Here is an
/// example where this arises with [FFI]. The foreign interface uses
/// handles of type `*mut ()` to refer to Rust values of different
/// types. We track the Rust type using a phantom type parameter on
/// the struct `ExternalResource` which wraps a handle.
///
/// [FFI]: ../../book/ffi.html
///
/// ```
/// # #![allow(dead_code)]
/// # trait ResType { }
/// # struct ParamType;
/// # mod foreign_lib {
/// # pub fn new(_: usize) -> *mut () { 42 as *mut () }
/// # pub fn do_stuff(_: *mut (), _: usize) {}
/// # pub fn new(_: usize) -> *mut () { 42 as *mut () }
/// # pub fn do_stuff(_: *mut (), _: usize) {}
/// # }
/// # fn convert_params(_: ParamType) -> usize { 42 }
/// use std::marker::PhantomData;
@ -389,21 +516,20 @@ macro_rules! impls{
/// }
/// ```
///
/// ## Indicating ownership
/// ## Ownership and the drop check
///
/// Adding a field of type `PhantomData<T>` also indicates that your
/// struct owns data of type `T`. This in turn implies that when your
/// struct is dropped, it may in turn drop one or more instances of
/// the type `T`, though that may not be apparent from the other
/// structure of the type itself. This is commonly necessary if the
/// structure is using a raw pointer like `*mut T` whose referent
/// may be dropped when the type is dropped, as a `*mut T` is
/// otherwise not treated as owned.
/// Adding a field of type `PhantomData<T>` indicates that your
/// type owns data of type `T`. This in turn implies that when your
/// type is dropped, it may drop one or more instances of the type
/// `T`. This has bearing on the Rust compiler's [drop check]
/// analysis.
///
/// If your struct does not in fact *own* the data of type `T`, it is
/// better to use a reference type, like `PhantomData<&'a T>`
/// (ideally) or `PhantomData<*const T>` (if no lifetime applies), so
/// as not to indicate ownership.
///
/// [drop check]: ../../nomicon/dropck.html
#[lang = "phantom_data"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct PhantomData<T:?Sized>;
@ -419,10 +545,13 @@ mod impls {
/// Types that can be reflected over.
///
/// This trait is implemented for all types. Its purpose is to ensure
/// that when you write a generic function that will employ
/// reflection, that must be reflected (no pun intended) in the
/// generic bounds of that function. Here is an example:
/// By "reflection" we mean use of the [`Any`][any] trait, or related
/// machinery such as [`TypeId`][typeid].
///
/// `Reflect` is implemented for all types. Its purpose is to ensure
/// that when you write a generic function that will employ reflection,
/// that must be reflected (no pun intended) in the generic bounds of
/// that function.
///
/// ```
/// #![feature(reflect_marker)]
@ -436,21 +565,24 @@ mod impls {
/// }
/// ```
///
/// Without the declaration `T: Reflect`, `foo` would not type check
/// (note: as a matter of style, it would be preferable to write
/// `T: Any`, because `T: Any` implies `T: Reflect` and `T: 'static`, but
/// we use `Reflect` here to show how it works). The `Reflect` bound
/// thus serves to alert `foo`'s caller to the fact that `foo` may
/// behave differently depending on whether `T = u32` or not. In
/// particular, thanks to the `Reflect` bound, callers know that a
/// function declared like `fn bar<T>(...)` will always act in
/// precisely the same way no matter what type `T` is supplied,
/// because there are no bounds declared on `T`. (The ability for a
/// caller to reason about what a function may do based solely on what
/// generic bounds are declared is often called the ["parametricity
/// property"][1].)
/// Without the bound `T: Reflect`, `foo` would not typecheck. (As
/// a matter of style, it would be preferable to write `T: Any`,
/// because `T: Any` implies `T: Reflect` and `T: 'static`, but we
/// use `Reflect` here for illustrative purposes.)
///
/// [1]: http://en.wikipedia.org/wiki/Parametricity
/// The `Reflect` bound serves to alert `foo`'s caller to the
/// fact that `foo` may behave differently depending on whether
/// `T` is `u32` or not. The ability for a caller to reason about what
/// a function may do based solely on what generic bounds are declared
/// is often called the "[parametricity property][param]". Despite the
/// use of `Reflect`, Rust lacks true parametricity because a generic
/// function can, at the very least, call [`mem::size_of`][size_of]
/// without employing any trait bounds whatsoever.
///
/// [any]: ../any/trait.Any.html
/// [typeid]: ../any/struct.TypeId.html
/// [param]: http://en.wikipedia.org/wiki/Parametricity
/// [size_of]: ../mem/fn.size_of.html
#[rustc_reflect_like]
#[unstable(feature = "reflect_marker",
reason = "requires RFC and more experience",

View file

@ -21,54 +21,39 @@ use ptr;
#[stable(feature = "rust1", since = "1.0.0")]
pub use intrinsics::transmute;
/// Leaks a value into the void, consuming ownership and never running its
/// destructor.
/// Leaks a value: takes ownership and "forgets" about the value **without running
/// its destructor**.
///
/// This function will take ownership of its argument, but is distinct from the
/// `mem::drop` function in that it **does not run the destructor**, leaking the
/// value and any resources that it owns.
/// Any resources the value manages, such as heap memory or a file handle, will linger
/// forever in an unreachable state.
///
/// There's only a few reasons to use this function. They mainly come
/// up in unsafe code or FFI code.
///
/// * You have an uninitialized value, perhaps for performance reasons, and
/// need to prevent the destructor from running on it.
/// * You have two copies of a value (like when writing something like
/// [`mem::swap`][swap]), but need the destructor to only run once to
/// prevent a double `free`.
/// * Transferring resources across [FFI][ffi] boundaries.
///
/// [swap]: fn.swap.html
/// [ffi]: ../../book/ffi.html
/// If you want to dispose of a value properly, running its destructor, see
/// [`mem::drop`][drop].
///
/// # Safety
///
/// This function is not marked as `unsafe` as Rust does not guarantee that the
/// `Drop` implementation for a value will always run. Note, however, that
/// leaking resources such as memory or I/O objects is likely not desired, so
/// this function is only recommended for specialized use cases.
/// `forget` is not marked as `unsafe`, because Rust's safety guarantees
/// do not include a guarantee that destructors will always run. For example,
/// a program can create a reference cycle using [`Rc`][rc], or call
/// [`process:exit`][exit] to exit without running destructors. Thus, allowing
/// `mem::forget` from safe code does not fundamentally change Rust's safety
/// guarantees.
///
/// The safety of this function implies that when writing `unsafe` code
/// yourself care must be taken when leveraging a destructor that is required to
/// run to preserve memory safety. There are known situations where the
/// destructor may not run (such as if ownership of the object with the
/// destructor is returned) which must be taken into account.
/// That said, leaking resources such as memory or I/O objects is usually undesirable,
/// so `forget` is only recommended for specialized use cases like those shown below.
///
/// # Other forms of Leakage
/// Because forgetting a value is allowed, any `unsafe` code you write must
/// allow for this possibility. You cannot return a value and expect that the
/// caller will necessarily run the value's destructor.
///
/// It's important to point out that this function is not the only method by
/// which a value can be leaked in safe Rust code. Other known sources of
/// leakage are:
/// [rc]: ../../std/rc/struct.Rc.html
/// [exit]: ../../std/process/fn.exit.html
///
/// * `Rc` and `Arc` cycles
/// * `mpsc::{Sender, Receiver}` cycles (they use `Arc` internally)
/// * Panicking destructors are likely to leak local resources
///
/// # Example
/// # Examples
///
/// Leak some heap memory by never deallocating it:
///
/// ```rust
/// ```
/// use std::mem;
///
/// let heap_memory = Box::new(3);
@ -77,7 +62,7 @@ pub use intrinsics::transmute;
///
/// Leak an I/O object, never closing the file:
///
/// ```rust,no_run
/// ```no_run
/// use std::mem;
/// use std::fs::File;
///
@ -85,9 +70,43 @@ pub use intrinsics::transmute;
/// mem::forget(file);
/// ```
///
/// The `mem::swap` function uses `mem::forget` to good effect:
/// The practical use cases for `forget` are rather specialized and mainly come
/// up in unsafe or FFI code.
///
/// ```rust
/// ## Use case 1
///
/// You have created an uninitialized value using [`mem::uninitialized`][uninit].
/// You must either initialize or `forget` it on every computation path before
/// Rust drops it automatically, like at the end of a scope or after a panic.
/// Running the destructor on an uninitialized value would be [undefined behavior][ub].
///
/// ```
/// use std::mem;
/// use std::ptr;
///
/// # let some_condition = false;
/// unsafe {
/// let mut uninit_vec: Vec<u32> = mem::uninitialized();
///
/// if some_condition {
/// // Initialize the variable.
/// ptr::write(&mut uninit_vec, Vec::new());
/// } else {
/// // Forget the uninitialized value so its destructor doesn't run.
/// mem::forget(uninit_vec);
/// }
/// }
/// ```
///
/// ## Use case 2
///
/// You have duplicated the bytes making up a value, without doing a proper
/// [`Clone`][clone]. You need the value's destructor to run only once,
/// because a double `free` is undefined behavior.
///
/// An example is the definition of [`mem::swap`][swap] in this module:
///
/// ```
/// use std::mem;
/// use std::ptr;
///
@ -109,6 +128,41 @@ pub use intrinsics::transmute;
/// }
/// }
/// ```
///
/// ## Use case 3
///
/// You are transferring ownership across a [FFI] boundary to code written in
/// another language. You need to `forget` the value on the Rust side because Rust
/// code is no longer responsible for it.
///
/// ```no_run
/// use std::mem;
///
/// extern "C" {
/// fn my_c_function(x: *const u32);
/// }
///
/// let x: Box<u32> = Box::new(3);
///
/// // Transfer ownership into C code.
/// unsafe {
/// my_c_function(&*x);
/// }
/// mem::forget(x);
/// ```
///
/// In this case, C code must call back into Rust to free the object. Calling C's `free`
/// function on a [`Box`][box] is *not* safe! Also, `Box` provides an [`into_raw`][into_raw]
/// method which is the preferred way to do this in practice.
///
/// [drop]: fn.drop.html
/// [uninit]: fn.uninitialized.html
/// [clone]: ../clone/trait.Clone.html
/// [swap]: fn.swap.html
/// [FFI]: ../../book/ffi.html
/// [box]: ../../std/boxed/struct.Box.html
/// [into_raw]: ../../std/boxed/struct.Box.html#method.into_raw
/// [ub]: ../../reference.html#behavior-considered-undefined
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn forget<T>(t: T) {
@ -133,7 +187,14 @@ pub fn size_of<T>() -> usize {
unsafe { intrinsics::size_of::<T>() }
}
/// Returns the size of the given value in bytes.
/// Returns the size of the pointed-to value in bytes.
///
/// This is usually the same as `size_of::<T>()`. However, when `T` *has* no
/// statically known size, e.g. a slice [`[T]`][slice] or a [trait object],
/// then `size_of_val` can be used to get the dynamically-known size.
///
/// [slice]: ../../std/primitive.slice.html
/// [trait object]: ../../book/trait-objects.html
///
/// # Examples
///
@ -141,6 +202,10 @@ pub fn size_of<T>() -> usize {
/// use std::mem;
///
/// assert_eq!(4, mem::size_of_val(&5i32));
///
/// let x: [u8; 13] = [0; 13];
/// let y: &[u8] = &x;
/// assert_eq!(13, mem::size_of_val(y));
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
@ -148,10 +213,14 @@ pub fn size_of_val<T: ?Sized>(val: &T) -> usize {
unsafe { intrinsics::size_of_val(val) }
}
/// Returns the ABI-required minimum alignment of a type
/// Returns the [ABI]-required minimum alignment of a type.
///
/// Every valid address of a value of the type `T` must be a multiple of this number.
///
/// This is the alignment used for struct fields. It may be smaller than the preferred alignment.
///
/// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface
///
/// # Examples
///
/// ```
@ -167,7 +236,11 @@ pub fn min_align_of<T>() -> usize {
unsafe { intrinsics::min_align_of::<T>() }
}
/// Returns the ABI-required minimum alignment of the type of the value that `val` points to
/// Returns the [ABI]-required minimum alignment of the type of the value that `val` points to.
///
/// Every valid address of a value of the type `T` must be a multiple of this number.
///
/// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface
///
/// # Examples
///
@ -184,10 +257,14 @@ pub fn min_align_of_val<T: ?Sized>(val: &T) -> usize {
unsafe { intrinsics::min_align_of_val(val) }
}
/// Returns the alignment in memory for a type.
/// Returns the [ABI]-required minimum alignment of a type.
///
/// Every valid address of a value of the type `T` must be a multiple of this number.
///
/// This is the alignment used for struct fields. It may be smaller than the preferred alignment.
///
/// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface
///
/// # Examples
///
/// ```
@ -201,7 +278,11 @@ pub fn align_of<T>() -> usize {
unsafe { intrinsics::min_align_of::<T>() }
}
/// Returns the ABI-required minimum alignment of the type of the value that `val` points to
/// Returns the [ABI]-required minimum alignment of the type of the value that `val` points to.
///
/// Every valid address of a value of the type `T` must be a multiple of this number.
///
/// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface
///
/// # Examples
///
@ -216,16 +297,23 @@ pub fn align_of_val<T: ?Sized>(val: &T) -> usize {
unsafe { intrinsics::min_align_of_val(val) }
}
/// Creates a value initialized to zero.
/// Creates a value whose bytes are all zero.
///
/// This function is similar to allocating space for a local variable and zeroing it out (an unsafe
/// operation).
/// This has the same effect as allocating space with
/// [`mem::uninitialized`][uninit] and then zeroing it out. It is useful for
/// [FFI] sometimes, but should generally be avoided.
///
/// Care must be taken when using this function, if the type `T` has a destructor and the value
/// falls out of scope (due to unwinding or returning) before being initialized, then the
/// destructor will run on zeroed data, likely leading to crashes.
/// There is no guarantee that an all-zero byte-pattern represents a valid value of
/// some type `T`. If `T` has a destructor and the value is destroyed (due to
/// a panic or the end of a scope) before being initialized, then the destructor
/// will run on zeroed data, likely leading to [undefined behavior][ub].
///
/// This is useful for FFI functions sometimes, but should generally be avoided.
/// See also the documentation for [`mem::uninitialized`][uninit], which has
/// many of the same caveats.
///
/// [uninit]: fn.uninitialized.html
/// [FFI]: ../../book/ffi.html
/// [ub]: ../../reference.html#behavior-considered-undefined
///
/// # Examples
///
@ -233,6 +321,7 @@ pub fn align_of_val<T: ?Sized>(val: &T) -> usize {
/// use std::mem;
///
/// let x: i32 = unsafe { mem::zeroed() };
/// assert_eq!(0, x);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
@ -241,32 +330,38 @@ pub unsafe fn zeroed<T>() -> T {
}
/// Bypasses Rust's normal memory-initialization checks by pretending to
/// produce a value of type T, while doing nothing at all.
/// produce a value of type `T`, while doing nothing at all.
///
/// **This is incredibly dangerous, and should not be done lightly. Deeply
/// consider initializing your memory with a default value instead.**
///
/// This is useful for FFI functions and initializing arrays sometimes,
/// This is useful for [FFI] functions and initializing arrays sometimes,
/// but should generally be avoided.
///
/// # Undefined Behavior
/// [FFI]: ../../book/ffi.html
///
/// It is Undefined Behavior to read uninitialized memory. Even just an
/// # Undefined behavior
///
/// It is [undefined behavior][ub] to read uninitialized memory, even just an
/// uninitialized boolean. For instance, if you branch on the value of such
/// a boolean your program may take one, both, or neither of the branches.
/// a boolean, your program may take one, both, or neither of the branches.
///
/// Note that this often also includes *writing* to the uninitialized value.
/// Rust believes the value is initialized, and will therefore try to Drop
/// the uninitialized value and its fields if you try to overwrite the memory
/// in a normal manner. The only way to safely initialize an arbitrary
/// uninitialized value is with one of the `ptr` functions: `write`, `copy`, or
/// `copy_nonoverlapping`. This isn't necessary if `T` is a primitive
/// or otherwise only contains types that don't implement Drop.
/// Writing to the uninitialized value is similarly dangerous. Rust believes the
/// value is initialized, and will therefore try to [`Drop`][drop] the uninitialized
/// value and its fields if you try to overwrite it in a normal manner. The only way
/// to safely initialize an uninitialized value is with [`ptr::write`][write],
/// [`ptr::copy`][copy], or [`ptr::copy_nonoverlapping`][copy_no].
///
/// If this value *does* need some kind of Drop, it must be initialized before
/// If the value does implement `Drop`, it must be initialized before
/// it goes out of scope (and therefore would be dropped). Note that this
/// includes a `panic` occurring and unwinding the stack suddenly.
///
/// [ub]: ../../reference.html#behavior-considered-undefined
/// [write]: ../ptr/fn.write.html
/// [copy]: ../intrinsics/fn.copy.html
/// [copy_no]: ../intrinsics/fn.copy_nonoverlapping.html
/// [drop]: ../ops/trait.Drop.html
///
/// # Examples
///
/// Here's how to safely initialize an array of `Vec`s.
@ -309,8 +404,8 @@ pub unsafe fn zeroed<T>() -> T {
/// println!("{:?}", &data[0]);
/// ```
///
/// This example emphasizes exactly how delicate and dangerous doing this is.
/// Note that the `vec!` macro *does* let you initialize every element with a
/// This example emphasizes exactly how delicate and dangerous using `mem::uninitialized`
/// can be. Note that the `vec!` macro *does* let you initialize every element with a
/// value that is only `Clone`, so the following is semantically equivalent and
/// vastly less dangerous, as long as you can live with an extra heap
/// allocation:
@ -325,21 +420,20 @@ pub unsafe fn uninitialized<T>() -> T {
intrinsics::uninit()
}
/// Swap the values at two mutable locations of the same type, without deinitializing or copying
/// either one.
/// Swaps the values at two mutable locations, without deinitializing either one.
///
/// # Examples
///
/// ```
/// use std::mem;
///
/// let x = &mut 5;
/// let y = &mut 42;
/// let mut x = 5;
/// let mut y = 42;
///
/// mem::swap(x, y);
/// mem::swap(&mut x, &mut y);
///
/// assert_eq!(42, *x);
/// assert_eq!(5, *y);
/// assert_eq!(42, x);
/// assert_eq!(5, y);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
@ -361,10 +455,7 @@ pub fn swap<T>(x: &mut T, y: &mut T) {
}
/// Replaces the value at a mutable location with a new one, returning the old value, without
/// deinitializing or copying either one.
///
/// This is primarily used for transferring and swapping ownership of a value in a mutable
/// location.
/// deinitializing either one.
///
/// # Examples
///
@ -373,15 +464,17 @@ pub fn swap<T>(x: &mut T, y: &mut T) {
/// ```
/// use std::mem;
///
/// let mut v: Vec<i32> = Vec::new();
/// let mut v: Vec<i32> = vec![1, 2];
///
/// mem::replace(&mut v, Vec::new());
/// let old_v = mem::replace(&mut v, vec![3, 4, 5]);
/// assert_eq!(2, old_v.len());
/// assert_eq!(3, v.len());
/// ```
///
/// This function allows consumption of one field of a struct by replacing it with another value.
/// The normal approach doesn't always work:
/// `replace` allows consumption of a struct field by replacing it with another value.
/// Without `replace` you can run into issues like these:
///
/// ```rust,ignore
/// ```ignore
/// struct Buffer<T> { buf: Vec<T> }
///
/// impl<T> Buffer<T> {
@ -401,6 +494,7 @@ pub fn swap<T>(x: &mut T, y: &mut T) {
/// ```
/// # #![allow(dead_code)]
/// use std::mem;
///
/// # struct Buffer<T> { buf: Vec<T> }
/// impl<T> Buffer<T> {
/// fn get_and_reset(&mut self) -> Vec<T> {
@ -417,14 +511,25 @@ pub fn replace<T>(dest: &mut T, mut src: T) -> T {
/// Disposes of a value.
///
/// While this does call the argument's implementation of `Drop`, it will not
/// release any borrows, as borrows are based on lexical scope.
/// While this does call the argument's implementation of [`Drop`][drop],
/// it will not release any borrows, as borrows are based on lexical scope.
///
/// This effectively does nothing for
/// [types which implement `Copy`](../../book/ownership.html#copy-types),
/// e.g. integers. Such values are copied and _then_ moved into the function,
/// so the value persists after this function call.
///
/// This function is not magic; it is literally defined as
///
/// ```
/// pub fn drop<T>(_x: T) { }
/// ```
///
/// Because `_x` is moved into the function, it is automatically dropped before
/// the function returns.
///
/// [drop]: ../ops/trait.Drop.html
///
/// # Examples
///
/// Basic usage:
@ -461,8 +566,8 @@ pub fn replace<T>(dest: &mut T, mut src: T) -> T {
/// v.push(4); // no problems
/// ```
///
/// Since `RefCell` enforces the borrow rules at runtime, `drop()` can
/// seemingly release a borrow of one:
/// Since `RefCell` enforces the borrow rules at runtime, `drop` can
/// release a `RefCell` borrow:
///
/// ```
/// use std::cell::RefCell;
@ -478,7 +583,7 @@ pub fn replace<T>(dest: &mut T, mut src: T) -> T {
/// println!("{}", *borrow);
/// ```
///
/// Integers and other types implementing `Copy` are unaffected by `drop()`
/// Integers and other types implementing `Copy` are unaffected by `drop`.
///
/// ```
/// #[derive(Copy, Clone)]
@ -496,19 +601,22 @@ pub fn replace<T>(dest: &mut T, mut src: T) -> T {
#[stable(feature = "rust1", since = "1.0.0")]
pub fn drop<T>(_x: T) { }
/// Interprets `src` as `&U`, and then reads `src` without moving the contained
/// value.
/// Interprets `src` as having type `&U`, and then reads `src` without moving
/// the contained value.
///
/// This function will unsafely assume the pointer `src` is valid for
/// `sizeof(U)` bytes by transmuting `&T` to `&U` and then reading the `&U`. It
/// will also unsafely create a copy of the contained value instead of moving
/// out of `src`.
/// [`size_of::<U>()`][size_of] bytes by transmuting `&T` to `&U` and then reading
/// the `&U`. It will also unsafely create a copy of the contained value instead of
/// moving out of `src`.
///
/// It is not a compile-time error if `T` and `U` have different sizes, but it
/// is highly encouraged to only invoke this function where `T` and `U` have the
/// same size. This function triggers undefined behavior if `U` is larger than
/// same size. This function triggers [undefined behavior][ub] if `U` is larger than
/// `T`.
///
/// [ub]: ../../reference.html#behavior-considered-undefined
/// [size_of]: fn.size_of.html
///
/// # Examples
///
/// ```

View file

@ -474,9 +474,9 @@ macro_rules! define_bignum {
let sz = if self.size < 1 {1} else {self.size};
let digitlen = mem::size_of::<$ty>() * 2;
try!(write!(f, "{:#x}", self.base[sz-1]));
write!(f, "{:#x}", self.base[sz-1])?;
for &v in self.base[..sz-1].iter().rev() {
try!(write!(f, "_{:01$x}", v, digitlen));
write!(f, "_{:01$x}", v, digitlen)?;
}
::result::Result::Ok(())
}

View file

@ -2211,25 +2211,21 @@ macro_rules! uint_impl {
let mut base = self;
let mut acc = 1;
let mut prev_base = self;
let mut base_oflo = false;
while exp > 0 {
while exp > 1 {
if (exp & 1) == 1 {
if base_oflo {
// ensure overflow occurs in the same manner it
// would have otherwise (i.e. signal any exception
// it would have otherwise).
acc = acc * (prev_base * prev_base);
} else {
acc = acc * base;
}
acc = acc * base;
}
prev_base = base;
let (new_base, new_base_oflo) = base.overflowing_mul(base);
base = new_base;
base_oflo = new_base_oflo;
exp /= 2;
base = base * base;
}
// Deal with the final bit of the exponent separately, since
// squaring the base afterwards is not necessary and may cause a
// needless overflow.
if exp == 1 {
acc = acc * base;
}
acc
}

View file

@ -282,6 +282,12 @@ macro_rules! forward_ref_binop {
/// Point { x: 3, y: 3 });
/// }
/// ```
///
/// Note that `RHS = Self` by default, but this is not mandatory. For example,
/// [std::time::SystemTime] implements `Add<Duration>`, which permits
/// operations of the form `SystemTime = SystemTime + Duration`.
///
/// [std::time::SystemTime]: ../../std/time/struct.SystemTime.html
#[lang = "add"]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Add<RHS=Self> {
@ -349,6 +355,12 @@ add_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
/// Point { x: 1, y: 0 });
/// }
/// ```
///
/// Note that `RHS = Self` by default, but this is not mandatory. For example,
/// [std::time::SystemTime] implements `Sub<Duration>`, which permits
/// operations of the form `SystemTime = SystemTime - Duration`.
///
/// [std::time::SystemTime]: ../../std/time/struct.SystemTime.html
#[lang = "sub"]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Sub<RHS=Self> {

View file

@ -10,9 +10,9 @@
//! Optional values.
//!
//! Type `Option` represents an optional value: every `Option`
//! is either `Some` and contains a value, or `None`, and
//! does not. `Option` types are very common in Rust code, as
//! Type [`Option`] represents an optional value: every [`Option`]
//! is either [`Some`] and contains a value, or [`None`], and
//! does not. [`Option`] types are very common in Rust code, as
//! they have a number of uses:
//!
//! * Initial values
@ -26,8 +26,8 @@
//! * Nullable pointers
//! * Swapping things out of difficult situations
//!
//! Options are commonly paired with pattern matching to query the presence
//! of a value and take action, always accounting for the `None` case.
//! [`Option`]s are commonly paired with pattern matching to query the presence
//! of a value and take action, always accounting for the [`None`] case.
//!
//! ```
//! fn divide(numerator: f64, denominator: f64) -> Option<f64> {
@ -57,13 +57,13 @@
//!
//! Rust's pointer types must always point to a valid location; there are
//! no "null" pointers. Instead, Rust has *optional* pointers, like
//! the optional owned box, `Option<Box<T>>`.
//! the optional owned box, [`Option`]`<`[`Box<T>`]`>`.
//!
//! The following example uses `Option` to create an optional box of
//! `i32`. Notice that in order to use the inner `i32` value first the
//! The following example uses [`Option`] to create an optional box of
//! [`i32`]. Notice that in order to use the inner [`i32`] value first the
//! `check_optional` function needs to use pattern matching to
//! determine whether the box has a value (i.e. it is `Some(...)`) or
//! not (`None`).
//! determine whether the box has a value (i.e. it is [`Some(...)`][`Some`]) or
//! not ([`None`]).
//!
//! ```
//! let optional: Option<Box<i32>> = None;
@ -80,14 +80,14 @@
//! }
//! ```
//!
//! This usage of `Option` to create safe nullable pointers is so
//! This usage of [`Option`] to create safe nullable pointers is so
//! common that Rust does special optimizations to make the
//! representation of `Option<Box<T>>` a single pointer. Optional pointers
//! representation of [`Option`]`<`[`Box<T>`]`>` a single pointer. Optional pointers
//! in Rust are stored as efficiently as any other pointer type.
//!
//! # Examples
//!
//! Basic pattern matching on `Option`:
//! Basic pattern matching on [`Option`]:
//!
//! ```
//! let msg = Some("howdy");
@ -101,7 +101,7 @@
//! let unwrapped_msg = msg.unwrap_or("default message");
//! ```
//!
//! Initialize a result to `None` before a loop:
//! Initialize a result to [`None`] before a loop:
//!
//! ```
//! enum Kingdom { Plant(u32, &'static str), Animal(u32, &'static str) }
@ -136,6 +136,12 @@
//! None => println!("there are no animals :("),
//! }
//! ```
//!
//! [`Option`]: enum.Option.html
//! [`Some`]: enum.Option.html#variant.Some
//! [`None`]: enum.Option.html#variant.None
//! [`Box<T>`]: ../../std/boxed/struct.Box.html
//! [`i32`]: ../../std/primitive.i32.html
#![stable(feature = "rust1", since = "1.0.0")]
@ -156,7 +162,7 @@ pub enum Option<T> {
None,
/// Some value `T`
#[stable(feature = "rust1", since = "1.0.0")]
Some(#[stable(feature = "rust1", since = "1.0.0")] T)
Some(#[stable(feature = "rust1", since = "1.0.0")] T),
}
/////////////////////////////////////////////////////////////////////////////
@ -168,7 +174,7 @@ impl<T> Option<T> {
// Querying the contained values
/////////////////////////////////////////////////////////////////////////
/// Returns `true` if the option is a `Some` value
/// Returns `true` if the option is a `Some` value.
///
/// # Examples
///
@ -188,7 +194,7 @@ impl<T> Option<T> {
}
}
/// Returns `true` if the option is a `None` value
/// Returns `true` if the option is a `None` value.
///
/// # Examples
///
@ -209,15 +215,17 @@ impl<T> Option<T> {
// Adapter for working with references
/////////////////////////////////////////////////////////////////////////
/// Converts from `Option<T>` to `Option<&T>`
/// Converts from `Option<T>` to `Option<&T>`.
///
/// # Examples
///
/// Convert an `Option<String>` into an `Option<usize>`, preserving the original.
/// The `map` method takes the `self` argument by value, consuming the original,
/// The [`map`] method takes the `self` argument by value, consuming the original,
/// so this technique uses `as_ref` to first take an `Option` to a reference
/// to the value inside the original.
///
/// [`map`]: enum.Option.html#method.map
///
/// ```
/// let num_as_str: Option<String> = Some("10".to_string());
/// // First, cast `Option<String>` to `Option<&String>` with `as_ref`,
@ -234,7 +242,7 @@ impl<T> Option<T> {
}
}
/// Converts from `Option<T>` to `Option<&mut T>`
/// Converts from `Option<T>` to `Option<&mut T>`.
///
/// # Examples
///
@ -357,7 +365,7 @@ impl<T> Option<T> {
// Transforming contained values
/////////////////////////////////////////////////////////////////////////
/// Maps an `Option<T>` to `Option<U>` by applying a function to a contained value
/// Maps an `Option<T>` to `Option<U>` by applying a function to a contained value.
///
/// # Examples
///
@ -423,8 +431,12 @@ impl<T> Option<T> {
}
}
/// Transforms the `Option<T>` into a `Result<T, E>`, mapping `Some(v)` to
/// `Ok(v)` and `None` to `Err(err)`.
/// Transforms the `Option<T>` into a [`Result<T, E>`], mapping `Some(v)` to
/// [`Ok(v)`] and `None` to [`Err(err)`][Err].
///
/// [`Result<T, E>`]: ../../std/result/enum.Result.html
/// [`Ok(v)`]: ../../std/result/enum.Result.html#variant.Ok
/// [Err]: ../../std/result/enum.Result.html#variant.Err
///
/// # Examples
///
@ -444,8 +456,12 @@ impl<T> Option<T> {
}
}
/// Transforms the `Option<T>` into a `Result<T, E>`, mapping `Some(v)` to
/// `Ok(v)` and `None` to `Err(err())`.
/// Transforms the `Option<T>` into a [`Result<T, E>`], mapping `Some(v)` to
/// [`Ok(v)`] and `None` to [`Err(err())`][Err].
///
/// [`Result<T, E>`]: ../../std/result/enum.Result.html
/// [`Ok(v)`]: ../../std/result/enum.Result.html#variant.Ok
/// [Err]: ../../std/result/enum.Result.html#variant.Err
///
/// # Examples
///
@ -698,6 +714,7 @@ fn expect_failed(msg: &str) -> ! {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Default for Option<T> {
/// Returns None.
#[inline]
fn default() -> Option<T> { None }
}
@ -789,7 +806,9 @@ impl<A> DoubleEndedIterator for Item<A> {
impl<A> ExactSizeIterator for Item<A> {}
impl<A> FusedIterator for Item<A> {}
/// An iterator over a reference of the contained item in an Option.
/// An iterator over a reference of the contained item in an [`Option`].
///
/// [`Option`]: enum.Option.html
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Debug)]
pub struct Iter<'a, A: 'a> { inner: Item<&'a A> }
@ -823,7 +842,9 @@ impl<'a, A> Clone for Iter<'a, A> {
}
}
/// An iterator over a mutable reference of the contained item in an Option.
/// An iterator over a mutable reference of the contained item in an [`Option`].
///
/// [`Option`]: enum.Option.html
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Debug)]
pub struct IterMut<'a, A: 'a> { inner: Item<&'a mut A> }
@ -850,7 +871,9 @@ impl<'a, A> ExactSizeIterator for IterMut<'a, A> {}
#[unstable(feature = "fused", issue = "35602")]
impl<'a, A> FusedIterator for IterMut<'a, A> {}
/// An iterator over the item contained inside an Option.
/// An iterator over the item contained inside an [`Option`].
///
/// [`Option`]: enum.Option.html
#[derive(Clone, Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct IntoIter<A> { inner: Item<A> }

View file

@ -479,6 +479,40 @@ impl<T: ?Sized> PartialEq for *mut T {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Eq for *mut T {}
/// Compare raw pointers for equality.
///
/// This is the same as using the `==` operator, but less generic:
/// the arguments have to be `*const T` raw pointers,
/// not anything that implements `PartialEq`.
///
/// This can be used to compare `&T` references (which coerce to `*const T` implicitly)
/// by their address rather than comparing the values they point to
/// (which is what the `PartialEq for &T` implementation does).
///
/// # Examples
///
/// ```
/// #![feature(ptr_eq)]
/// use std::ptr;
///
/// let five = 5;
/// let other_five = 5;
/// let five_ref = &five;
/// let same_five_ref = &five;
/// let other_five_ref = &other_five;
///
/// assert!(five_ref == same_five_ref);
/// assert!(five_ref == other_five_ref);
///
/// assert!(ptr::eq(five_ref, same_five_ref));
/// assert!(!ptr::eq(five_ref, other_five_ref));
/// ```
#[unstable(feature = "ptr_eq", reason = "newly added", issue = "36497")]
#[inline]
pub fn eq<T: ?Sized>(a: *const T, b: *const T) -> bool {
a == b
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Clone for *const T {
#[inline]

View file

@ -10,9 +10,9 @@
//! Error handling with the `Result` type.
//!
//! `Result<T, E>` is the type used for returning and propagating
//! errors. It is an enum with the variants, `Ok(T)`, representing
//! success and containing a value, and `Err(E)`, representing error
//! [`Result<T, E>`][`Result`] is the type used for returning and propagating
//! errors. It is an enum with the variants, [`Ok(T)`], representing
//! success and containing a value, and [`Err(E)`], representing error
//! and containing an error value.
//!
//! ```
@ -23,11 +23,11 @@
//! }
//! ```
//!
//! Functions return `Result` whenever errors are expected and
//! recoverable. In the `std` crate `Result` is most prominently used
//! Functions return [`Result`] whenever errors are expected and
//! recoverable. In the `std` crate, [`Result`] is most prominently used
//! for [I/O](../../std/io/index.html).
//!
//! A simple function returning `Result` might be
//! A simple function returning [`Result`] might be
//! defined and used like so:
//!
//! ```
@ -50,8 +50,8 @@
//! }
//! ```
//!
//! Pattern matching on `Result`s is clear and straightforward for
//! simple cases, but `Result` comes with some convenience methods
//! Pattern matching on [`Result`]s is clear and straightforward for
//! simple cases, but [`Result`] comes with some convenience methods
//! that make working with it more succinct.
//!
//! ```
@ -80,14 +80,14 @@
//!
//! A common problem with using return values to indicate errors is
//! that it is easy to ignore the return value, thus failing to handle
//! the error. Result is annotated with the #[must_use] attribute,
//! the error. [`Result`] is annotated with the `#[must_use]` attribute,
//! which will cause the compiler to issue a warning when a Result
//! value is ignored. This makes `Result` especially useful with
//! value is ignored. This makes [`Result`] especially useful with
//! functions that may encounter errors but don't otherwise return a
//! useful value.
//!
//! Consider the `write_all` method defined for I/O types
//! by the [`Write`](../../std/io/trait.Write.html) trait:
//! Consider the [`write_all`] method defined for I/O types
//! by the [`Write`] trait:
//!
//! ```
//! use std::io;
@ -97,8 +97,8 @@
//! }
//! ```
//!
//! *Note: The actual definition of `Write` uses `io::Result`, which
//! is just a synonym for `Result<T, io::Error>`.*
//! *Note: The actual definition of [`Write`] uses [`io::Result`], which
//! is just a synonym for [`Result`]`<T, `[`io::Error`]`>`.*
//!
//! This method doesn't produce a value, but the write may
//! fail. It's crucial to handle the error case, and *not* write
@ -119,7 +119,7 @@
//! warning (by default, controlled by the `unused_must_use` lint).
//!
//! You might instead, if you don't want to handle the error, simply
//! assert success with `expect`. This will panic if the
//! assert success with [`expect`]. This will panic if the
//! write fails, providing a marginally useful message indicating why:
//!
//! ```{.no_run}
@ -139,7 +139,7 @@
//! assert!(file.write_all(b"important message").is_ok());
//! ```
//!
//! Or propagate the error up the call stack with `try!`:
//! Or propagate the error up the call stack with [`try!`]:
//!
//! ```
//! # use std::fs::File;
@ -156,7 +156,7 @@
//! # The `try!` macro
//!
//! When writing code that calls many functions that return the
//! `Result` type, the error handling can be tedious. The `try!`
//! [`Result`] type, the error handling can be tedious. The [`try!`]
//! macro hides some of the boilerplate of propagating errors up the
//! call stack.
//!
@ -219,9 +219,9 @@
//!
//! *It's much nicer!*
//!
//! Wrapping an expression in `try!` will result in the unwrapped
//! success (`Ok`) value, unless the result is `Err`, in which case
//! `Err` is returned early from the enclosing function. Its simple definition
//! Wrapping an expression in [`try!`] will result in the unwrapped
//! success ([`Ok`]) value, unless the result is [`Err`], in which case
//! [`Err`] is returned early from the enclosing function. Its simple definition
//! makes it clear:
//!
//! ```
@ -230,9 +230,21 @@
//! }
//! ```
//!
//! `try!` is imported by the prelude and is available everywhere, but it can only
//! be used in functions that return `Result` because of the early return of
//! `Err` that it provides.
//! [`try!`] is imported by the prelude and is available everywhere, but it can only
//! be used in functions that return [`Result`] because of the early return of
//! [`Err`] that it provides.
//!
//! [`expect`]: enum.Result.html#method.expect
//! [`Write`]: ../../std/io/trait.Write.html
//! [`write_all`]: ../../std/io/trait.Write.html#method.write_all
//! [`io::Result`]: ../../std/io/type.Result.html
//! [`try!`]: ../../std/macro.try.html
//! [`Result`]: enum.Result.html
//! [`Ok(T)`]: enum.Result.html#variant.Ok
//! [`Err(E)`]: enum.Result.html#variant.Err
//! [`io::Error`]: ../../std/io/struct.Error.html
//! [`Ok`]: enum.Result.html#variant.Ok
//! [`Err`]: enum.Result.html#variant.Err
#![stable(feature = "rust1", since = "1.0.0")]
@ -264,7 +276,7 @@ impl<T, E> Result<T, E> {
// Querying the contained values
/////////////////////////////////////////////////////////////////////////
/// Returns true if the result is `Ok`
/// Returns true if the result is `Ok`.
///
/// # Examples
///
@ -286,7 +298,7 @@ impl<T, E> Result<T, E> {
}
}
/// Returns true if the result is `Err`
/// Returns true if the result is `Err`.
///
/// # Examples
///
@ -309,11 +321,13 @@ impl<T, E> Result<T, E> {
// Adapter for each variant
/////////////////////////////////////////////////////////////////////////
/// Converts from `Result<T, E>` to `Option<T>`
/// Converts from `Result<T, E>` to [`Option<T>`].
///
/// Converts `self` into an `Option<T>`, consuming `self`,
/// Converts `self` into an [`Option<T>`], consuming `self`,
/// and discarding the error, if any.
///
/// [`Option<T>`]: ../../std/option/enum.Option.html
///
/// # Examples
///
/// Basic usage:
@ -334,11 +348,13 @@ impl<T, E> Result<T, E> {
}
}
/// Converts from `Result<T, E>` to `Option<E>`
/// Converts from `Result<T, E>` to [`Option<E>`].
///
/// Converts `self` into an `Option<E>`, consuming `self`,
/// Converts `self` into an [`Option<E>`], consuming `self`,
/// and discarding the success value, if any.
///
/// [`Option<E>`]: ../../std/option/enum.Option.html
///
/// # Examples
///
/// Basic usage:
@ -363,7 +379,7 @@ impl<T, E> Result<T, E> {
// Adapter for working with references
/////////////////////////////////////////////////////////////////////////
/// Converts from `Result<T, E>` to `Result<&T, &E>`
/// Converts from `Result<T, E>` to `Result<&T, &E>`.
///
/// Produces a new `Result`, containing a reference
/// into the original, leaving the original in place.
@ -388,7 +404,7 @@ impl<T, E> Result<T, E> {
}
}
/// Converts from `Result<T, E>` to `Result<&mut T, &mut E>`
/// Converts from `Result<T, E>` to `Result<&mut T, &mut E>`.
///
/// # Examples
///
@ -563,7 +579,7 @@ impl<T, E> Result<T, E> {
/// Calls `op` if the result is `Ok`, otherwise returns the `Err` value of `self`.
///
/// This function can be used for control flow based on result values.
/// This function can be used for control flow based on `Result` values.
///
/// # Examples
///
@ -646,7 +662,7 @@ impl<T, E> Result<T, E> {
}
/// Unwraps a result, yielding the content of an `Ok`.
/// Else it returns `optb`.
/// Else, it returns `optb`.
///
/// # Examples
///
@ -837,7 +853,10 @@ impl<'a, T, E> IntoIterator for &'a mut Result<T, E> {
// The Result Iterators
/////////////////////////////////////////////////////////////////////////////
/// An iterator over a reference to the `Ok` variant of a `Result`.
/// An iterator over a reference to the [`Ok`] variant of a [`Result`].
///
/// [`Ok`]: enum.Result.html#variant.Ok
/// [`Result`]: enum.Result.html
#[derive(Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Iter<'a, T: 'a> { inner: Option<&'a T> }
@ -872,7 +891,10 @@ impl<'a, T> Clone for Iter<'a, T> {
fn clone(&self) -> Iter<'a, T> { Iter { inner: self.inner } }
}
/// An iterator over a mutable reference to the `Ok` variant of a `Result`.
/// An iterator over a mutable reference to the [`Ok`] variant of a [`Result`].
///
/// [`Ok`]: enum.Result.html#variant.Ok
/// [`Result`]: enum.Result.html
#[derive(Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct IterMut<'a, T: 'a> { inner: Option<&'a mut T> }
@ -902,7 +924,14 @@ impl<'a, T> ExactSizeIterator for IterMut<'a, T> {}
#[unstable(feature = "fused", issue = "35602")]
impl<'a, T> FusedIterator for IterMut<'a, T> {}
/// An iterator over the value in a `Ok` variant of a `Result`.
/// An iterator over the value in a [`Ok`] variant of a [`Result`]. This struct is
/// created by the [`into_iter`] method on [`Result`][`Result`] (provided by
/// the [`IntoIterator`] trait).
///
/// [`Ok`]: enum.Result.html#variant.Ok
/// [`Result`]: enum.Result.html
/// [`into_iter`]: ../iter/trait.IntoIterator.html#tymethod.into_iter
/// [`IntoIterator`]: ../iter/trait.IntoIterator.html
#[derive(Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct IntoIter<T> { inner: Option<T> }

View file

@ -520,8 +520,8 @@ impl<T> ops::Index<usize> for [T] {
type Output = T;
fn index(&self, index: usize) -> &T {
assert!(index < self.len());
unsafe { self.get_unchecked(index) }
// NB built-in indexing
&(*self)[index]
}
}
@ -530,8 +530,8 @@ impl<T> ops::Index<usize> for [T] {
impl<T> ops::IndexMut<usize> for [T] {
#[inline]
fn index_mut(&mut self, index: usize) -> &mut T {
assert!(index < self.len());
unsafe { self.get_unchecked_mut(index) }
// NB built-in indexing
&mut (*self)[index]
}
}
@ -755,11 +755,13 @@ impl<T> ops::IndexMut<ops::RangeToInclusive<usize>> for [T] {
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> Default for &'a [T] {
/// Creates an empty slice.
fn default() -> &'a [T] { &[] }
}
#[stable(feature = "mut_slice_default", since = "1.5.0")]
impl<'a, T> Default for &'a mut [T] {
/// Creates a mutable empty slice.
fn default() -> &'a mut [T] { &mut [] }
}
@ -1821,7 +1823,8 @@ impl<T: PartialOrd> PartialOrd for [T] {
// intermediate trait for specialization of slice's PartialEq
trait SlicePartialEq<B> {
fn equal(&self, other: &[B]) -> bool;
fn not_equal(&self, other: &[B]) -> bool;
fn not_equal(&self, other: &[B]) -> bool { !self.equal(other) }
}
// Generic slice equality
@ -1841,20 +1844,6 @@ impl<A, B> SlicePartialEq<B> for [A]
true
}
default fn not_equal(&self, other: &[B]) -> bool {
if self.len() != other.len() {
return true;
}
for i in 0..self.len() {
if self[i].ne(&other[i]) {
return true;
}
}
false
}
}
// Use memcmp for bytewise equality when the types allow
@ -1874,10 +1863,6 @@ impl<A> SlicePartialEq<A> for [A]
other.as_ptr() as *const u8, size) == 0
}
}
fn not_equal(&self, other: &[A]) -> bool {
!self.equal(other)
}
}
#[doc(hidden)]

View file

@ -1987,5 +1987,6 @@ impl AsRef<[u8]> for str {
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> Default for &'a str {
/// Creates an empty str
fn default() -> &'a str { "" }
}

View file

@ -95,6 +95,7 @@ pub struct AtomicBool {
#[cfg(target_has_atomic = "8")]
#[stable(feature = "rust1", since = "1.0.0")]
impl Default for AtomicBool {
/// Creates an `AtomicBool` initialised as false.
fn default() -> Self {
Self::new(false)
}
@ -117,6 +118,7 @@ pub struct AtomicPtr<T> {
#[cfg(target_has_atomic = "ptr")]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Default for AtomicPtr<T> {
/// Creates a null `AtomicPtr<T>`.
fn default() -> AtomicPtr<T> {
AtomicPtr::new(::ptr::null_mut())
}

View file

@ -664,12 +664,24 @@ fn test_max_by_key() {
assert_eq!(*xs.iter().max_by_key(|x| x.abs()).unwrap(), -10);
}
#[test]
fn test_max_by() {
let xs: &[isize] = &[-3, 0, 1, 5, -10];
assert_eq!(*xs.iter().max_by(|x, y| x.abs().cmp(&y.abs())).unwrap(), -10);
}
#[test]
fn test_min_by_key() {
let xs: &[isize] = &[-3, 0, 1, 5, -10];
assert_eq!(*xs.iter().min_by_key(|x| x.abs()).unwrap(), 0);
}
#[test]
fn test_min_by() {
let xs: &[isize] = &[-3, 0, 1, 5, -10];
assert_eq!(*xs.iter().min_by(|x, y| x.abs().cmp(&y.abs())).unwrap(), 0);
}
#[test]
fn test_by_ref() {
let mut xs = 0..10;

View file

@ -32,6 +32,8 @@
#![feature(try_from)]
#![feature(unicode)]
#![feature(unique)]
#![feature(iter_max_by)]
#![feature(iter_min_by)]
extern crate core;
extern crate test;

View file

@ -279,7 +279,7 @@ impl OptGroup {
}],
}
}
(_, _) => panic!("something is wrong with the long-form opt"),
_ => panic!("something is wrong with the long-form opt"),
}
}
}

@ -1 +1 @@
Subproject commit 5066b7dcab7e700844b0e2ba71b8af9dc627a59b
Subproject commit d4f6a19c55a03e3f9f6fb7377911b37ed807eb6c

View file

@ -124,12 +124,15 @@ const UNWIND_DATA_REG: (i32, i32) = (0, 1); // RAX, RDX
#[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
const UNWIND_DATA_REG: (i32, i32) = (0, 1); // R0, R1 / X0, X1
#[cfg(any(target_arch = "mips", target_arch = "mipsel"))]
#[cfg(any(target_arch = "mips", target_arch = "mipsel", target_arch = "mips64"))]
const UNWIND_DATA_REG: (i32, i32) = (4, 5); // A0, A1
#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
const UNWIND_DATA_REG: (i32, i32) = (3, 4); // R3, R4 / X3, X4
#[cfg(target_arch = "s390x")]
const UNWIND_DATA_REG: (i32, i32) = (6, 7); // R6, R7
// The following code is based on GCC's C and C++ personality routines. For reference, see:
// https://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/libsupc++/eh_personality.cc
// https://github.com/gcc-mirror/gcc/blob/trunk/libgcc/unwind-c.c

View file

@ -232,13 +232,13 @@ extern "C" {
// Again, I'm not entirely sure what this is describing, it just seems to work.
#[cfg_attr(not(test), lang = "msvc_try_filter")]
static mut TYPE_DESCRIPTOR1: _TypeDescriptor = _TypeDescriptor {
pVFTable: &TYPE_INFO_VTABLE as *const _ as *const _,
pVFTable: unsafe { &TYPE_INFO_VTABLE } as *const _ as *const _,
spare: 0 as *mut _,
name: imp::NAME1,
};
static mut TYPE_DESCRIPTOR2: _TypeDescriptor = _TypeDescriptor {
pVFTable: &TYPE_INFO_VTABLE as *const _ as *const _,
pVFTable: unsafe { &TYPE_INFO_VTABLE } as *const _ as *const _,
spare: 0 as *mut _,
name: imp::NAME2,
};

View file

@ -113,6 +113,7 @@ impl<R: Rng + Default> Reseeder<R> for ReseedWithDefault {
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Default for ReseedWithDefault {
/// Creates an instance of `ReseedWithDefault`.
fn default() -> ReseedWithDefault {
ReseedWithDefault
}
@ -137,6 +138,7 @@ mod tests {
}
}
impl Default for Counter {
/// Constructs a `Counter` with initial value zero.
fn default() -> Counter {
Counter { i: 0 }
}

File diff suppressed because it is too large Load diff

View file

@ -14,7 +14,6 @@ flate = { path = "../libflate" }
fmt_macros = { path = "../libfmt_macros" }
graphviz = { path = "../libgraphviz" }
log = { path = "../liblog" }
rbml = { path = "../librbml" }
rustc_back = { path = "../librustc_back" }
rustc_bitflags = { path = "../librustc_bitflags" }
rustc_const_math = { path = "../librustc_const_math" }

View file

@ -99,7 +99,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
fn pat(&mut self, pat: &hir::Pat, pred: CFGIndex) -> CFGIndex {
match pat.node {
PatKind::Binding(_, _, None) |
PatKind::Binding(.., None) |
PatKind::Path(..) |
PatKind::Lit(..) |
PatKind::Range(..) |
@ -109,7 +109,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
PatKind::Box(ref subpat) |
PatKind::Ref(ref subpat, _) |
PatKind::Binding(_, _, Some(ref subpat)) => {
PatKind::Binding(.., Some(ref subpat)) => {
let subpat_exit = self.pat(&subpat, pred);
self.add_ast_node(pat.id, &[subpat_exit])
}
@ -306,7 +306,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
self.call(expr, pred, &func, args.iter().map(|e| &**e))
}
hir::ExprMethodCall(_, _, ref args) => {
hir::ExprMethodCall(.., ref args) => {
self.call(expr, pred, &args[0], args[1..].iter().map(|e| &**e))
}

View file

@ -341,6 +341,8 @@ path is found (as demonstrated above).
### Debugging the dependency graph
#### Dumping the graph
The compiler is also capable of dumping the dependency graph for your
debugging pleasure. To do so, pass the `-Z dump-dep-graph` flag. The
graph will be dumped to `dep_graph.{txt,dot}` in the current
@ -392,6 +394,35 @@ This will dump out all the nodes that lead from `Hir(foo)` to
`TypeckItemBody(bar)`, from which you can (hopefully) see the source
of the erroneous edge.
#### Tracking down incorrect edges
Sometimes, after you dump the dependency graph, you will find some
path that should not exist, but you will not be quite sure how it came
to be. **When the compiler is built with debug assertions,** it can
help you track that down. Simply set the `RUST_FORBID_DEP_GRAPH_EDGE`
environment variable to a filter. Every edge created in the dep-graph
will be tested against that filter -- if it matches, a `bug!` is
reported, so you can easily see the backtrace (`RUST_BACKTRACE=1`).
The syntax for these filters is the same as described in the previous
section. However, note that this filter is applied to every **edge**
and doesn't handle longer paths in the graph, unlike the previous
section.
Example:
You find that there is a path from the `Hir` of `foo` to the type
check of `bar` and you don't think there should be. You dump the
dep-graph as described in the previous section and open `dep-graph.txt`
to see something like:
Hir(foo) -> Collect(bar)
Collect(bar) -> TypeckItemBody(bar)
That first edge looks suspicious to you. So you set
`RUST_FORBID_DEP_GRAPH_EDGE` to `Hir&foo -> Collect&bar`, re-run, and
then observe the backtrace. Voila, bug fixed!
### Inlining of HIR nodes
For the time being, at least, we still sometimes "inline" HIR nodes

View file

@ -66,4 +66,11 @@ impl EdgeFilter {
})
}
}
pub fn test<D: Clone + Debug>(&self,
source: &DepNode<D>,
target: &DepNode<D>)
-> bool {
self.source.test(source) && self.target.test(target)
}
}

View file

@ -103,18 +103,13 @@ pub enum DepNode<D: Clone + Debug> {
// table in the tcx (or elsewhere) maps to one of these
// nodes. Often we map multiple tables to the same node if there
// is no point in distinguishing them (e.g., both the type and
// predicates for an item wind up in `ItemSignature`). Other
// times, such as `ImplItems` vs `TraitItemDefIds`, tables which
// might be mergable are kept distinct because the sets of def-ids
// to which they apply are disjoint, and hence we might as well
// have distinct labels for easier debugging.
// predicates for an item wind up in `ItemSignature`).
ImplOrTraitItems(D),
ItemSignature(D),
FieldTy(D),
SizedConstraint(D),
TraitItemDefIds(D),
ImplOrTraitItemDefIds(D),
InherentImpls(D),
ImplItems(D),
// The set of impls for a given trait. Ultimately, it would be
// nice to get more fine-grained here (e.g., to include a
@ -132,7 +127,7 @@ pub enum DepNode<D: Clone + Debug> {
// which would yield an overly conservative dep-graph.
TraitItems(D),
ReprHints(D),
TraitSelect(D, Vec<D>),
TraitSelect(Vec<D>),
}
impl<D: Clone + Debug> DepNode<D> {
@ -162,9 +157,8 @@ impl<D: Clone + Debug> DepNode<D> {
ImplOrTraitItems,
ItemSignature,
FieldTy,
TraitItemDefIds,
ImplOrTraitItemDefIds,
InherentImpls,
ImplItems,
TraitImpls,
ReprHints,
}
@ -231,16 +225,14 @@ impl<D: Clone + Debug> DepNode<D> {
ItemSignature(ref d) => op(d).map(ItemSignature),
FieldTy(ref d) => op(d).map(FieldTy),
SizedConstraint(ref d) => op(d).map(SizedConstraint),
TraitItemDefIds(ref d) => op(d).map(TraitItemDefIds),
ImplOrTraitItemDefIds(ref d) => op(d).map(ImplOrTraitItemDefIds),
InherentImpls(ref d) => op(d).map(InherentImpls),
ImplItems(ref d) => op(d).map(ImplItems),
TraitImpls(ref d) => op(d).map(TraitImpls),
TraitItems(ref d) => op(d).map(TraitItems),
ReprHints(ref d) => op(d).map(ReprHints),
TraitSelect(ref d, ref type_ds) => {
let d = try_opt!(op(d));
TraitSelect(ref type_ds) => {
let type_ds = try_opt!(type_ds.iter().map(|d| op(d)).collect());
Some(TraitSelect(d, type_ds))
Some(TraitSelect(type_ds))
}
}
}

View file

@ -80,6 +80,17 @@ impl<M: DepTrackingMapConfig> DepTrackingMap<M> {
pub fn keys(&self) -> Vec<M::Key> {
self.map.keys().cloned().collect()
}
/// Append `elem` to the vector stored for `k`, creating a new vector if needed.
/// This is considered a write to `k`.
pub fn push<E: Clone>(&mut self, k: M::Key, elem: E)
where M: DepTrackingMapConfig<Value=Vec<E>>
{
self.write(&k);
self.map.entry(k)
.or_insert(Vec::new())
.push(elem);
}
}
impl<M: DepTrackingMapConfig> MemoizationMap for RefCell<DepTrackingMap<M>> {

View file

@ -46,7 +46,7 @@ impl DepGraph {
data: Rc::new(DepGraphData {
thread: DepGraphThreadData::new(enabled),
previous_work_products: RefCell::new(FnvHashMap()),
work_products: RefCell::new(FnvHashMap())
work_products: RefCell::new(FnvHashMap()),
})
}
}

View file

@ -15,6 +15,7 @@ mod edges;
mod graph;
mod query;
mod raii;
mod shadow;
mod thread;
mod visit;

View file

@ -47,3 +47,4 @@ impl<'graph> Drop for IgnoreTask<'graph> {
self.data.enqueue(DepMessage::PopIgnore);
}
}

View file

@ -0,0 +1,145 @@
// Copyright 2012-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.
//! The "Shadow Graph" is maintained on the main thread and which
//! tracks each message relating to the dep-graph and applies some
//! sanity checks as they go by. If an error results, it means you get
//! a nice stack-trace telling you precisely what caused the error.
//!
//! NOTE: This is a debugging facility which can potentially have non-trivial
//! runtime impact. Therefore, it is largely compiled out if
//! debug-assertions are not enabled.
//!
//! The basic sanity check, enabled if you have debug assertions
//! enabled, is that there is always a task (or ignore) on the stack
//! when you do read/write, and that the tasks are pushed/popped
//! according to a proper stack discipline.
//!
//! Optionally, if you specify RUST_FORBID_DEP_GRAPH_EDGE, you can
//! specify an edge filter to be applied to each edge as it is
//! created. See `./README.md` for details.
use hir::def_id::DefId;
use std::cell::{BorrowState, RefCell};
use std::env;
use super::DepNode;
use super::thread::DepMessage;
use super::debug::EdgeFilter;
pub struct ShadowGraph {
// if you push None onto the stack, that corresponds to an Ignore
stack: RefCell<Vec<Option<DepNode<DefId>>>>,
forbidden_edge: Option<EdgeFilter>,
}
const ENABLED: bool = cfg!(debug_assertions);
impl ShadowGraph {
pub fn new() -> Self {
let forbidden_edge = if !ENABLED {
None
} else {
match env::var("RUST_FORBID_DEP_GRAPH_EDGE") {
Ok(s) => {
match EdgeFilter::new(&s) {
Ok(f) => Some(f),
Err(err) => bug!("RUST_FORBID_DEP_GRAPH_EDGE invalid: {}", err),
}
}
Err(_) => None,
}
};
ShadowGraph {
stack: RefCell::new(vec![]),
forbidden_edge: forbidden_edge,
}
}
pub fn enqueue(&self, message: &DepMessage) {
if ENABLED {
match self.stack.borrow_state() {
BorrowState::Unused => {}
_ => {
// When we apply edge filters, that invokes the
// Debug trait on DefIds, which in turn reads from
// various bits of state and creates reads! Ignore
// those recursive reads.
return;
}
}
let mut stack = self.stack.borrow_mut();
match *message {
DepMessage::Read(ref n) => self.check_edge(Some(Some(n)), top(&stack)),
DepMessage::Write(ref n) => self.check_edge(top(&stack), Some(Some(n))),
DepMessage::PushTask(ref n) => stack.push(Some(n.clone())),
DepMessage::PushIgnore => stack.push(None),
DepMessage::PopTask(ref n) => {
match stack.pop() {
Some(Some(m)) => {
if *n != m {
bug!("stack mismatch: found {:?} expected {:?}", m, n)
}
}
Some(None) => bug!("stack mismatch: found Ignore expected {:?}", n),
None => bug!("stack mismatch: found empty stack, expected {:?}", n),
}
}
DepMessage::PopIgnore => {
match stack.pop() {
Some(Some(m)) => bug!("stack mismatch: found {:?} expected ignore", m),
Some(None) => (),
None => bug!("stack mismatch: found empty stack, expected ignore"),
}
}
DepMessage::Query => (),
}
}
}
fn check_edge(&self,
source: Option<Option<&DepNode<DefId>>>,
target: Option<Option<&DepNode<DefId>>>) {
assert!(ENABLED);
match (source, target) {
// cannot happen, one side is always Some(Some(_))
(None, None) => unreachable!(),
// nothing on top of the stack
(None, Some(n)) | (Some(n), None) => bug!("read/write of {:?} but no current task", n),
// this corresponds to an Ignore being top of the stack
(Some(None), _) | (_, Some(None)) => (),
// a task is on top of the stack
(Some(Some(source)), Some(Some(target))) => {
if let Some(ref forbidden_edge) = self.forbidden_edge {
if forbidden_edge.test(source, target) {
bug!("forbidden edge {:?} -> {:?} created", source, target)
}
}
}
}
}
}
// Do a little juggling: we get back a reference to an option at the
// top of the stack, convert it to an optional reference.
fn top<'s>(stack: &'s Vec<Option<DepNode<DefId>>>) -> Option<Option<&'s DepNode<DefId>>> {
stack.last()
.map(|n: &'s Option<DepNode<DefId>>| -> Option<&'s DepNode<DefId>> {
// (*)
// (*) type annotation just there to clarify what would
// otherwise be some *really* obscure code
n.as_ref()
})
}

View file

@ -20,13 +20,13 @@
use hir::def_id::DefId;
use rustc_data_structures::veccell::VecCell;
use std::cell::Cell;
use std::sync::mpsc::{self, Sender, Receiver};
use std::thread;
use super::DepGraphQuery;
use super::DepNode;
use super::edges::DepGraphEdges;
use super::shadow::ShadowGraph;
#[derive(Debug)]
pub enum DepMessage {
@ -42,12 +42,16 @@ pub enum DepMessage {
pub struct DepGraphThreadData {
enabled: bool,
// Local counter that just tracks how many tasks are pushed onto the
// stack, so that we still get an error in the case where one is
// missing. If dep-graph construction is enabled, we'd get the same
// error when processing tasks later on, but that's annoying because
// it lacks precision about the source of the error.
tasks_pushed: Cell<usize>,
// The "shadow graph" is a debugging aid. We give it each message
// in real time as it arrives and it checks for various errors
// (for example, a read/write when there is no current task; it
// can also apply user-defined filters; see `shadow` module for
// details). This only occurs if debug-assertions are enabled.
//
// Note that in some cases the same errors will occur when the
// data is processed off the main thread, but that's annoying
// because it lacks precision about the source of the error.
shadow_graph: ShadowGraph,
// current buffer, where we accumulate messages
messages: VecCell<DepMessage>,
@ -76,7 +80,7 @@ impl DepGraphThreadData {
DepGraphThreadData {
enabled: enabled,
tasks_pushed: Cell::new(0),
shadow_graph: ShadowGraph::new(),
messages: VecCell::with_capacity(INITIAL_CAPACITY),
swap_in: rx2,
swap_out: tx1,
@ -118,21 +122,7 @@ impl DepGraphThreadData {
/// the buffer is full, this may swap.)
#[inline]
pub fn enqueue(&self, message: DepMessage) {
// Regardless of whether dep graph construction is enabled, we
// still want to check that we always have a valid task on the
// stack when a read/write/etc event occurs.
match message {
DepMessage::Read(_) | DepMessage::Write(_) =>
if self.tasks_pushed.get() == 0 {
self.invalid_message("read/write but no current task")
},
DepMessage::PushTask(_) | DepMessage::PushIgnore =>
self.tasks_pushed.set(self.tasks_pushed.get() + 1),
DepMessage::PopTask(_) | DepMessage::PopIgnore =>
self.tasks_pushed.set(self.tasks_pushed.get() - 1),
DepMessage::Query =>
(),
}
self.shadow_graph.enqueue(&message);
if self.enabled {
self.enqueue_enabled(message);
@ -147,11 +137,6 @@ impl DepGraphThreadData {
self.swap();
}
}
// Outline this too.
fn invalid_message(&self, string: &str) {
bug!("{}; see src/librustc/dep_graph/README.md for more information", string)
}
}
/// Definition of the depgraph thread.

View file

@ -18,6 +18,7 @@ use syntax::visit::Visitor;
enum Target {
Fn,
Struct,
Union,
Enum,
Other,
}
@ -27,6 +28,7 @@ impl Target {
match item.node {
ast::ItemKind::Fn(..) => Target::Fn,
ast::ItemKind::Struct(..) => Target::Struct,
ast::ItemKind::Union(..) => Target::Union,
ast::ItemKind::Enum(..) => Target::Enum,
_ => Target::Other,
}
@ -40,7 +42,9 @@ struct CheckAttrVisitor<'a> {
impl<'a> CheckAttrVisitor<'a> {
fn check_inline(&self, attr: &ast::Attribute, target: Target) {
if target != Target::Fn {
span_err!(self.sess, attr.span, E0518, "attribute should be applied to function");
struct_span_err!(self.sess, attr.span, E0518, "attribute should be applied to function")
.span_label(attr.span, &format!("requires a function"))
.emit();
}
}
@ -54,16 +58,20 @@ impl<'a> CheckAttrVisitor<'a> {
let mut conflicting_reprs = 0;
for word in words {
let name = match word.name() {
Some(word) => word,
None => continue,
};
let message = match &*name {
let (message, label) = match &*name {
"C" => {
conflicting_reprs += 1;
if target != Target::Struct && target != Target::Enum {
"attribute should be applied to struct or enum"
if target != Target::Struct &&
target != Target::Union &&
target != Target::Enum {
("attribute should be applied to struct, enum or union",
"a struct, enum or union")
} else {
continue
}
@ -71,8 +79,10 @@ impl<'a> CheckAttrVisitor<'a> {
"packed" => {
// Do not increment conflicting_reprs here, because "packed"
// can be used to modify another repr hint
if target != Target::Struct {
"attribute should be applied to struct"
if target != Target::Struct &&
target != Target::Union {
("attribute should be applied to struct or union",
"a struct or union")
} else {
continue
}
@ -80,7 +90,8 @@ impl<'a> CheckAttrVisitor<'a> {
"simd" => {
conflicting_reprs += 1;
if target != Target::Struct {
"attribute should be applied to struct"
("attribute should be applied to struct",
"a struct")
} else {
continue
}
@ -90,15 +101,17 @@ impl<'a> CheckAttrVisitor<'a> {
"isize" | "usize" => {
conflicting_reprs += 1;
if target != Target::Enum {
"attribute should be applied to enum"
("attribute should be applied to enum",
"an enum")
} else {
continue
}
}
_ => continue,
};
span_err!(self.sess, attr.span, E0517, "{}", message);
struct_span_err!(self.sess, attr.span, E0517, "{}", message)
.span_label(attr.span, &format!("requires {}", label))
.emit();
}
if conflicting_reprs > 1 {
span_warn!(self.sess, attr.span, E0566,

View file

@ -16,23 +16,20 @@ use hir;
#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum Def {
Fn(DefId),
SelfTy(Option<DefId> /* trait */, Option<ast::NodeId> /* impl */),
SelfTy(Option<DefId> /* trait */, Option<DefId> /* impl */),
Mod(DefId),
ForeignMod(DefId),
Static(DefId, bool /* is_mutbl */),
Const(DefId),
AssociatedConst(DefId),
Local(DefId, // def id of variable
ast::NodeId), // node id of variable
Variant(DefId /* enum */, DefId /* variant */),
Local(DefId),
Variant(DefId),
Enum(DefId),
TyAlias(DefId),
AssociatedTy(DefId /* trait */, DefId),
AssociatedTy(DefId),
Trait(DefId),
PrimTy(hir::PrimTy),
TyParam(DefId),
Upvar(DefId, // def id of closed over local
ast::NodeId, // node id of closed over local
usize, // index in the freevars list of the closure
ast::NodeId), // expr node that creates the closure
@ -41,6 +38,7 @@ pub enum Def {
// If Def::Struct lives in value namespace (e.g. tuple struct, unit struct expressions)
// it denotes a constructor and its DefId refers to NodeId of the struct's constructor.
Struct(DefId),
Union(DefId),
Label(ast::NodeId),
Method(DefId),
Err,
@ -93,37 +91,20 @@ pub type DefMap = NodeMap<PathResolution>;
// within.
pub type ExportMap = NodeMap<Vec<Export>>;
#[derive(Copy, Clone)]
#[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
pub struct Export {
pub name: ast::Name, // The name of the target.
pub def_id: DefId, // The definition of the target.
}
impl Def {
pub fn var_id(&self) -> ast::NodeId {
match *self {
Def::Local(_, id) |
Def::Upvar(_, id, _, _) => {
id
}
Def::Fn(..) | Def::Mod(..) | Def::ForeignMod(..) | Def::Static(..) |
Def::Variant(..) | Def::Enum(..) | Def::TyAlias(..) | Def::AssociatedTy(..) |
Def::TyParam(..) | Def::Struct(..) | Def::Trait(..) |
Def::Method(..) | Def::Const(..) | Def::AssociatedConst(..) |
Def::PrimTy(..) | Def::Label(..) | Def::SelfTy(..) | Def::Err => {
bug!("attempted .var_id() on invalid {:?}", self)
}
}
}
pub fn def_id(&self) -> DefId {
match *self {
Def::Fn(id) | Def::Mod(id) | Def::ForeignMod(id) | Def::Static(id, _) |
Def::Variant(_, id) | Def::Enum(id) | Def::TyAlias(id) | Def::AssociatedTy(_, id) |
Def::TyParam(id) | Def::Struct(id) | Def::Trait(id) |
Def::Fn(id) | Def::Mod(id) | Def::Static(id, _) |
Def::Variant(id) | Def::Enum(id) | Def::TyAlias(id) | Def::AssociatedTy(id) |
Def::TyParam(id) | Def::Struct(id) | Def::Union(id) | Def::Trait(id) |
Def::Method(id) | Def::Const(id) | Def::AssociatedConst(id) |
Def::Local(id, _) | Def::Upvar(id, _, _, _) => {
Def::Local(id) | Def::Upvar(id, ..) => {
id
}
@ -140,13 +121,13 @@ impl Def {
match *self {
Def::Fn(..) => "function",
Def::Mod(..) => "module",
Def::ForeignMod(..) => "foreign module",
Def::Static(..) => "static",
Def::Variant(..) => "variant",
Def::Enum(..) => "enum",
Def::TyAlias(..) => "type",
Def::AssociatedTy(..) => "associated type",
Def::Struct(..) => "struct",
Def::Union(..) => "union",
Def::Trait(..) => "trait",
Def::Method(..) => "method",
Def::Const(..) => "constant",

View file

@ -8,12 +8,69 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use middle::cstore::LOCAL_CRATE;
use ty;
use syntax::ast::CrateNum;
use rustc_data_structures::indexed_vec::Idx;
use serialize::{self, Encoder, Decoder};
use std::fmt;
use std::u32;
#[derive(Clone, Copy, Eq, Ord, PartialOrd, PartialEq, Hash, Debug)]
pub struct CrateNum(u32);
impl Idx for CrateNum {
fn new(value: usize) -> Self {
assert!(value < (u32::MAX) as usize);
CrateNum(value as u32)
}
fn index(self) -> usize {
self.0 as usize
}
}
/// Item definitions in the currently-compiled crate would have the CrateNum
/// LOCAL_CRATE in their DefId.
pub const LOCAL_CRATE: CrateNum = CrateNum(0);
impl CrateNum {
pub fn new(x: usize) -> CrateNum {
assert!(x < (u32::MAX as usize));
CrateNum(x as u32)
}
pub fn from_u32(x: u32) -> CrateNum {
CrateNum(x)
}
pub fn as_usize(&self) -> usize {
self.0 as usize
}
pub fn as_u32(&self) -> u32 {
self.0
}
}
impl fmt::Display for CrateNum {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&self.0, f)
}
}
impl serialize::UseSpecializedEncodable for CrateNum {
fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
s.emit_u32(self.0)
}
}
impl serialize::UseSpecializedDecodable for CrateNum {
fn default_decode<D: Decoder>(d: &mut D) -> Result<CrateNum, D::Error> {
d.read_u32().map(CrateNum)
}
}
/// A DefIndex is an index into the hir-map for a crate, identifying a
/// particular definition. It should really be considered an interned
/// shorthand for a particular DefPath.
@ -46,8 +103,7 @@ pub const CRATE_DEF_INDEX: DefIndex = DefIndex(0);
/// A DefId identifies a particular *definition*, by combining a crate
/// index and a def index.
#[derive(Clone, Eq, Ord, PartialOrd, PartialEq, RustcEncodable,
RustcDecodable, Hash, Copy)]
#[derive(Clone, Eq, Ord, PartialOrd, PartialEq, RustcEncodable, RustcDecodable, Hash, Copy)]
pub struct DefId {
pub krate: CrateNum,
pub index: DefIndex,
@ -58,19 +114,14 @@ impl fmt::Debug for DefId {
write!(f, "DefId {{ krate: {:?}, node: {:?}",
self.krate, self.index)?;
// Unfortunately, there seems to be no way to attempt to print
// a path for a def-id, so I'll just make a best effort for now
// and otherwise fallback to just printing the crate/node pair
if self.is_local() { // (1)
// (1) side-step fact that not all external things have paths at
// the moment, such as type parameters
ty::tls::with_opt(|opt_tcx| {
if let Some(tcx) = opt_tcx {
write!(f, " => {}", tcx.item_path_str(*self))?;
ty::tls::with_opt(|opt_tcx| {
if let Some(tcx) = opt_tcx {
if let Some(def_path) = tcx.opt_def_path(*self) {
write!(f, " => {}", def_path.to_string(tcx))?;
}
Ok(())
})?;
}
}
Ok(())
})?;
write!(f, " }}")
}

File diff suppressed because it is too large Load diff

View file

@ -49,8 +49,8 @@ pub enum FnKind<'a> {
impl<'a> FnKind<'a> {
pub fn attrs(&self) -> &'a [Attribute] {
match *self {
FnKind::ItemFn(_, _, _, _, _, _, attrs) => attrs,
FnKind::Method(_, _, _, attrs) => attrs,
FnKind::ItemFn(.., attrs) => attrs,
FnKind::Method(.., attrs) => attrs,
FnKind::Closure(attrs) => attrs,
}
}
@ -341,14 +341,15 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
visitor.visit_id(item.id);
visitor.visit_trait_ref(trait_ref)
}
ItemImpl(_, _, ref type_parameters, ref opt_trait_reference, ref typ, ref impl_items) => {
ItemImpl(.., ref type_parameters, ref opt_trait_reference, ref typ, ref impl_items) => {
visitor.visit_id(item.id);
visitor.visit_generics(type_parameters);
walk_list!(visitor, visit_trait_ref, opt_trait_reference);
visitor.visit_ty(typ);
walk_list!(visitor, visit_impl_item, impl_items);
}
ItemStruct(ref struct_definition, ref generics) => {
ItemStruct(ref struct_definition, ref generics) |
ItemUnion(ref struct_definition, ref generics) => {
visitor.visit_generics(generics);
visitor.visit_id(item.id);
visitor.visit_variant_data(struct_definition, item.name, generics, item.id, item.span);
@ -621,10 +622,10 @@ pub fn walk_fn_decl_nopat<'v, V: Visitor<'v>>(visitor: &mut V, function_declarat
pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V, function_kind: FnKind<'v>) {
match function_kind {
FnKind::ItemFn(_, generics, _, _, _, _, _) => {
FnKind::ItemFn(_, generics, ..) => {
visitor.visit_generics(generics);
}
FnKind::Method(_, sig, _, _) => {
FnKind::Method(_, sig, ..) => {
visitor.visit_generics(&sig.generics);
}
FnKind::Closure(_) => {}
@ -880,8 +881,8 @@ pub struct IdRange {
impl IdRange {
pub fn max() -> IdRange {
IdRange {
min: u32::MAX,
max: u32::MIN,
min: NodeId::from_u32(u32::MAX),
max: NodeId::from_u32(u32::MIN),
}
}
@ -895,7 +896,7 @@ impl IdRange {
pub fn add(&mut self, id: NodeId) {
self.min = cmp::min(self.min, id);
self.max = cmp::max(self.max, id + 1);
self.max = cmp::max(self.max, NodeId::from_u32(id.as_u32() + 1));
}
}

View file

@ -61,7 +61,7 @@ use syntax_pos::Span;
pub struct LoweringContext<'a> {
crate_root: Option<&'static str>,
// Use to assign ids to hir nodes that do not directly correspond to an ast node
sess: Option<&'a Session>,
sess: &'a Session,
// As we walk the AST we must keep track of the current 'parent' def id (in
// the form of a DefIndex) so that if we create a new node which introduces
// a definition, then we can properly create the def id.
@ -81,21 +81,7 @@ pub trait Resolver {
// We must keep the set of definitions up to date as we add nodes that weren't in the AST.
// This should only return `None` during testing.
fn definitions(&mut self) -> Option<&mut Definitions>;
}
pub struct DummyResolver;
impl Resolver for DummyResolver {
fn resolve_generated_global_path(&mut self, _path: &hir::Path, _is_value: bool) -> Def {
Def::Err
}
fn get_resolution(&mut self, _id: NodeId) -> Option<PathResolution> {
None
}
fn record_resolution(&mut self, _id: NodeId, _def: Def) {}
fn definitions(&mut self) -> Option<&mut Definitions> {
None
}
fn definitions(&mut self) -> &mut Definitions;
}
pub fn lower_crate(sess: &Session,
@ -115,22 +101,13 @@ pub fn lower_crate(sess: &Session,
} else {
Some("std")
},
sess: Some(sess),
sess: sess,
parent_def: None,
resolver: resolver,
}.lower_crate(krate)
}
impl<'a> LoweringContext<'a> {
pub fn testing_context(resolver: &'a mut Resolver) -> Self {
LoweringContext {
crate_root: None,
sess: None,
parent_def: None,
resolver: resolver,
}
}
fn lower_crate(&mut self, c: &Crate) -> hir::Crate {
struct ItemLowerer<'lcx, 'interner: 'lcx> {
items: BTreeMap<NodeId, hir::Item>,
@ -161,12 +138,11 @@ impl<'a> LoweringContext<'a> {
}
fn next_id(&self) -> NodeId {
self.sess.map(Session::next_node_id).unwrap_or(0)
self.sess.next_node_id()
}
fn diagnostic(&self) -> &errors::Handler {
self.sess.map(Session::diagnostic)
.unwrap_or_else(|| panic!("this lowerer cannot emit diagnostics"))
self.sess.diagnostic()
}
fn str_to_ident(&self, s: &'static str) -> Name {
@ -177,9 +153,9 @@ impl<'a> LoweringContext<'a> {
where F: FnOnce(&mut LoweringContext) -> T
{
let old_def = self.parent_def;
self.parent_def = match self.resolver.definitions() {
Some(defs) => Some(defs.opt_def_index(parent_id).unwrap()),
None => old_def,
self.parent_def = {
let defs = self.resolver.definitions();
Some(defs.opt_def_index(parent_id).unwrap())
};
let result = f(self);
@ -638,7 +614,10 @@ impl<'a> LoweringContext<'a> {
let struct_def = self.lower_variant_data(struct_def);
hir::ItemStruct(struct_def, self.lower_generics(generics))
}
ItemKind::Union(..) => panic!("`union` is not yet implemented"),
ItemKind::Union(ref vdata, ref generics) => {
let vdata = self.lower_variant_data(vdata);
hir::ItemUnion(vdata, self.lower_generics(generics))
}
ItemKind::DefaultImpl(unsafety, ref trait_ref) => {
hir::ItemDefaultImpl(self.lower_unsafety(unsafety),
self.lower_trait_ref(trait_ref))
@ -1716,9 +1695,10 @@ impl<'a> LoweringContext<'a> {
let expr_path = hir::ExprPath(None, self.path_ident(span, id));
let expr = self.expr(span, expr_path, ThinVec::new());
let def = self.resolver.definitions().map(|defs| {
Def::Local(defs.local_def_id(binding), binding)
}).unwrap_or(Def::Err);
let def = {
let defs = self.resolver.definitions();
Def::Local(defs.local_def_id(binding))
};
self.resolver.record_resolution(expr.id, def);
expr
@ -1866,11 +1846,12 @@ impl<'a> LoweringContext<'a> {
let pat = self.pat(span, pat_ident);
let parent_def = self.parent_def;
let def = self.resolver.definitions().map(|defs| {
let def = {
let defs = self.resolver.definitions();
let def_path_data = DefPathData::Binding(name.as_str());
let def_index = defs.create_def_with_parent(parent_def, pat.id, def_path_data);
Def::Local(DefId::local(def_index), pat.id)
}).unwrap_or(Def::Err);
Def::Local(DefId::local(def_index))
};
self.resolver.record_resolution(pat.id, def);
pat

View file

@ -27,6 +27,10 @@ pub struct NodeCollector<'ast> {
pub map: Vec<MapEntry<'ast>>,
/// The parent of this node
pub parent_node: NodeId,
/// If true, completely ignore nested items. We set this when loading
/// HIR from metadata, since in that case we only want the HIR for
/// one specific item (and not the ones nested inside of it).
pub ignore_nested_items: bool
}
impl<'ast> NodeCollector<'ast> {
@ -35,6 +39,7 @@ impl<'ast> NodeCollector<'ast> {
krate: krate,
map: vec![],
parent_node: CRATE_NODE_ID,
ignore_nested_items: false
};
collector.insert_entry(CRATE_NODE_ID, RootCrate);
@ -52,6 +57,7 @@ impl<'ast> NodeCollector<'ast> {
krate: krate,
map: map,
parent_node: parent_node,
ignore_nested_items: true
};
assert_eq!(parent_def_path.krate, parent_def_id.krate);
@ -63,10 +69,10 @@ impl<'ast> NodeCollector<'ast> {
fn insert_entry(&mut self, id: NodeId, entry: MapEntry<'ast>) {
debug!("ast_map: {:?} => {:?}", id, entry);
let len = self.map.len();
if id as usize >= len {
self.map.extend(repeat(NotPresent).take(id as usize - len + 1));
if id.as_usize() >= len {
self.map.extend(repeat(NotPresent).take(id.as_usize() - len + 1));
}
self.map[id as usize] = entry;
self.map[id.as_usize()] = entry;
}
fn insert(&mut self, id: NodeId, node: Node<'ast>) {
@ -88,7 +94,9 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
/// their outer items.
fn visit_nested_item(&mut self, item: ItemId) {
debug!("visit_nested_item: {:?}", item);
self.visit_item(self.krate.item(item.id))
if !self.ignore_nested_items {
self.visit_item(self.krate.item(item.id))
}
}
fn visit_item(&mut self, i: &'ast Item) {
@ -109,7 +117,7 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
this.insert(struct_def.id(), NodeStructCtor(struct_def));
}
}
ItemTrait(_, _, ref bounds, _) => {
ItemTrait(.., ref bounds, _) => {
for b in bounds.iter() {
if let TraitTyParamBound(ref t, TraitBoundModifier::None) = *b {
this.insert(t.trait_ref.ref_id, NodeItem(i));

View file

@ -285,15 +285,6 @@ impl<'ast> visit::Visitor for DefCollector<'ast> {
// We walk the HIR rather than the AST when reading items from metadata.
impl<'ast> intravisit::Visitor<'ast> for DefCollector<'ast> {
/// Because we want to track parent items and so forth, enable
/// deep walking so that we walk nested items in the context of
/// their outer items.
fn visit_nested_item(&mut self, item_id: hir::ItemId) {
debug!("visit_nested_item: {:?}", item_id);
let item = self.hir_crate.unwrap().item(item_id.id);
self.visit_item(item)
}
fn visit_item(&mut self, i: &'ast hir::Item) {
debug!("visit_item: {:?}", i);
@ -302,9 +293,9 @@ impl<'ast> intravisit::Visitor<'ast> for DefCollector<'ast> {
let def_data = match i.node {
hir::ItemDefaultImpl(..) | hir::ItemImpl(..) =>
DefPathData::Impl,
hir::ItemEnum(..) | hir::ItemStruct(..) | hir::ItemTrait(..) |
hir::ItemExternCrate(..) | hir::ItemMod(..) | hir::ItemForeignMod(..) |
hir::ItemTy(..) =>
hir::ItemEnum(..) | hir::ItemStruct(..) | hir::ItemUnion(..) |
hir::ItemTrait(..) | hir::ItemExternCrate(..) | hir::ItemMod(..) |
hir::ItemForeignMod(..) | hir::ItemTy(..) =>
DefPathData::TypeNs(i.name.as_str()),
hir::ItemStatic(..) | hir::ItemConst(..) | hir::ItemFn(..) =>
DefPathData::ValueNs(i.name.as_str()),
@ -331,7 +322,8 @@ impl<'ast> intravisit::Visitor<'ast> for DefCollector<'ast> {
});
}
}
hir::ItemStruct(ref struct_def, _) => {
hir::ItemStruct(ref struct_def, _) |
hir::ItemUnion(ref struct_def, _) => {
// If this is a tuple-like struct, register the constructor.
if !struct_def.is_struct() {
this.create_def(struct_def.id(),

View file

@ -8,14 +8,13 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use middle::cstore::LOCAL_CRATE;
use hir::def_id::{DefId, DefIndex};
use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE};
use hir::map::def_collector::DefCollector;
use rustc_data_structures::fnv::FnvHashMap;
use std::fmt::Write;
use std::hash::{Hash, Hasher, SipHasher};
use syntax::{ast, visit};
use syntax::parse::token::InternedString;
use syntax::parse::token::{self, InternedString};
use ty::TyCtxt;
use util::nodemap::NodeMap;
@ -70,7 +69,7 @@ pub struct DefPath {
pub data: Vec<DisambiguatedDefPathData>,
/// what krate root is this path relative to?
pub krate: ast::CrateNum,
pub krate: CrateNum,
}
impl DefPath {
@ -78,7 +77,7 @@ impl DefPath {
self.krate == LOCAL_CRATE
}
pub fn make<FN>(start_krate: ast::CrateNum,
pub fn make<FN>(start_krate: CrateNum,
start_index: DefIndex,
mut get_key: FN) -> DefPath
where FN: FnMut(DefIndex) -> DefKey
@ -116,11 +115,7 @@ impl DefPath {
pub fn to_string(&self, tcx: TyCtxt) -> String {
let mut s = String::with_capacity(self.data.len() * 16);
if self.krate == LOCAL_CRATE {
s.push_str(&tcx.crate_name(self.krate));
} else {
s.push_str(&tcx.sess.cstore.original_crate_name(self.krate));
}
s.push_str(&tcx.original_crate_name(self.krate));
s.push_str("/");
s.push_str(&tcx.crate_disambiguator(self.krate));
@ -142,7 +137,7 @@ impl DefPath {
}
pub fn deterministic_hash_to<H: Hasher>(&self, tcx: TyCtxt, state: &mut H) {
tcx.crate_name(self.krate).hash(state);
tcx.original_crate_name(self.krate).hash(state);
tcx.crate_disambiguator(self.krate).hash(state);
self.data.hash(state);
}
@ -327,6 +322,30 @@ impl Definitions {
}
impl DefPathData {
pub fn get_opt_name(&self) -> Option<ast::Name> {
use self::DefPathData::*;
match *self {
TypeNs(ref name) |
ValueNs(ref name) |
Module(ref name) |
MacroDef(ref name) |
TypeParam(ref name) |
LifetimeDef(ref name) |
EnumVariant(ref name) |
Binding(ref name) |
Field(ref name) => Some(token::intern(name)),
Impl |
CrateRoot |
InlinedRoot(_) |
Misc |
ClosureExpr |
StructCtor |
Initializer |
ImplTrait => None
}
}
pub fn as_interned_str(&self) -> InternedString {
use self::DefPathData::*;
match *self {

View file

@ -22,17 +22,15 @@ use middle::cstore::InlinedItem as II;
use hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndex};
use syntax::abi::Abi;
use syntax::ast::{self, Name, NodeId, DUMMY_NODE_ID, };
use syntax::ast::{self, Name, NodeId, CRATE_NODE_ID};
use syntax::codemap::Spanned;
use syntax_pos::Span;
use hir::*;
use hir::fold::Folder;
use hir::print as pprust;
use arena::TypedArena;
use std::cell::RefCell;
use std::cmp;
use std::io;
use std::mem;
@ -240,7 +238,7 @@ impl<'ast> Map<'ast> {
let mut id = id0;
if !self.is_inlined_node_id(id) {
loop {
match map[id as usize] {
match map[id.as_usize()] {
EntryItem(_, item) => {
let def_id = self.local_def_id(item.id);
// NB ^~~~~~~
@ -295,7 +293,7 @@ impl<'ast> Map<'ast> {
// reading from an inlined def-id is really a read out of
// the metadata from which we loaded the item.
loop {
match map[id as usize] {
match map[id.as_usize()] {
EntryItem(p, _) |
EntryForeignItem(p, _) |
EntryTraitItem(p, _) |
@ -373,7 +371,7 @@ impl<'ast> Map<'ast> {
}
fn find_entry(&self, id: NodeId) -> Option<MapEntry<'ast>> {
self.map.borrow().get(id as usize).cloned()
self.map.borrow().get(id.as_usize()).cloned()
}
pub fn krate(&self) -> &'ast Crate {
@ -456,8 +454,8 @@ impl<'ast> Map<'ast> {
let mut id = start_id;
loop {
let parent_node = self.get_parent_node(id);
if parent_node == 0 {
return Ok(0);
if parent_node == CRATE_NODE_ID {
return Ok(CRATE_NODE_ID);
}
if parent_node == id {
return Err(id);
@ -582,22 +580,24 @@ impl<'ast> Map<'ast> {
}
}
pub fn expect_struct(&self, id: NodeId) -> &'ast VariantData {
pub fn expect_variant_data(&self, id: NodeId) -> &'ast VariantData {
match self.find(id) {
Some(NodeItem(i)) => {
match i.node {
ItemStruct(ref struct_def, _) => struct_def,
_ => bug!("struct ID bound to non-struct")
ItemStruct(ref struct_def, _) |
ItemUnion(ref struct_def, _) => struct_def,
_ => {
bug!("struct ID bound to non-struct {}",
self.node_to_string(id));
}
}
}
Some(NodeVariant(variant)) => {
if variant.node.data.is_struct() {
&variant.node.data
} else {
bug!("struct ID bound to enum variant that isn't struct-like")
}
Some(NodeStructCtor(data)) => data,
Some(NodeVariant(variant)) => &variant.node.data,
_ => {
bug!("expected struct or variant, found {}",
self.node_to_string(id));
}
_ => bug!("expected struct, found {}", self.node_to_string(id)),
}
}
@ -680,7 +680,7 @@ impl<'ast> Map<'ast> {
map: self,
item_name: parts.last().unwrap(),
in_which: &parts[..parts.len() - 1],
idx: 0,
idx: CRATE_NODE_ID,
}
}
@ -801,10 +801,10 @@ impl<'a, 'ast> Iterator for NodesMatchingSuffix<'a, 'ast> {
fn next(&mut self) -> Option<NodeId> {
loop {
let idx = self.idx;
if idx as usize >= self.map.entry_count() {
if idx.as_usize() >= self.map.entry_count() {
return None;
}
self.idx += 1;
self.idx = NodeId::from_u32(self.idx.as_u32() + 1);
let name = match self.map.find_entry(idx) {
Some(EntryItem(_, n)) => n.name(),
Some(EntryForeignItem(_, n))=> n.name(),
@ -832,57 +832,6 @@ impl Named for Variant_ { fn name(&self) -> Name { self.name } }
impl Named for TraitItem { fn name(&self) -> Name { self.name } }
impl Named for ImplItem { fn name(&self) -> Name { self.name } }
pub trait FoldOps {
fn new_id(&self, id: NodeId) -> NodeId {
id
}
fn new_def_id(&self, def_id: DefId) -> DefId {
def_id
}
fn new_span(&self, span: Span) -> Span {
span
}
}
/// A Folder that updates IDs and Span's according to fold_ops.
pub struct IdAndSpanUpdater<F> {
fold_ops: F,
min_id_assigned: NodeId,
max_id_assigned: NodeId,
}
impl<F: FoldOps> IdAndSpanUpdater<F> {
pub fn new(fold_ops: F) -> IdAndSpanUpdater<F> {
IdAndSpanUpdater {
fold_ops: fold_ops,
min_id_assigned: ::std::u32::MAX,
max_id_assigned: ::std::u32::MIN,
}
}
pub fn id_range(&self) -> intravisit::IdRange {
intravisit::IdRange {
min: self.min_id_assigned,
max: self.max_id_assigned + 1,
}
}
}
impl<F: FoldOps> Folder for IdAndSpanUpdater<F> {
fn new_id(&mut self, id: NodeId) -> NodeId {
let id = self.fold_ops.new_id(id);
self.min_id_assigned = cmp::min(self.min_id_assigned, id);
self.max_id_assigned = cmp::max(self.max_id_assigned, id);
id
}
fn new_span(&mut self, span: Span) -> Span {
self.fold_ops.new_span(span)
}
}
pub fn map_crate<'ast>(forest: &'ast mut Forest,
definitions: Definitions)
-> Map<'ast> {
@ -906,7 +855,7 @@ pub fn map_crate<'ast>(forest: &'ast mut Forest,
entries, vector_length, (entries as f64 / vector_length as f64) * 100.);
}
let local_node_id_watermark = map.len() as NodeId;
let local_node_id_watermark = NodeId::new(map.len());
let local_def_id_watermark = definitions.len();
Map {
@ -921,34 +870,15 @@ pub fn map_crate<'ast>(forest: &'ast mut Forest,
/// Used for items loaded from external crate that are being inlined into this
/// crate.
pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>,
parent_def_path: DefPath,
parent_def_id: DefId,
ii: InlinedItem,
fold_ops: F)
-> &'ast InlinedItem {
let mut fld = IdAndSpanUpdater::new(fold_ops);
let ii = match ii {
II::Item(d, i) => II::Item(fld.fold_ops.new_def_id(d),
i.map(|i| fld.fold_item(i))),
II::TraitItem(d, ti) => {
II::TraitItem(fld.fold_ops.new_def_id(d),
ti.map(|ti| fld.fold_trait_item(ti)))
}
II::ImplItem(d, ii) => {
II::ImplItem(fld.fold_ops.new_def_id(d),
ii.map(|ii| fld.fold_impl_item(ii)))
}
};
pub fn map_decoded_item<'ast>(map: &Map<'ast>,
parent_def_path: DefPath,
parent_def_id: DefId,
ii: InlinedItem,
ii_parent_id: NodeId)
-> &'ast InlinedItem {
let _ignore = map.forest.dep_graph.in_ignore();
let ii = map.forest.inlined_items.alloc(ii);
let ii_parent_id = fld.new_id(DUMMY_NODE_ID);
// Assert that the ii_parent_id is the last NodeId in our reserved range
assert!(ii_parent_id == fld.max_id_assigned);
// Assert that we did not violate the invariant that all inlined HIR items
// have NodeIds greater than or equal to `local_node_id_watermark`
assert!(fld.min_id_assigned >= map.local_node_id_watermark);
let defs = &mut *map.definitions.borrow_mut();
let mut def_collector = DefCollector::extend(ii_parent_id,
@ -1030,6 +960,7 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
ItemTy(..) => "ty",
ItemEnum(..) => "enum",
ItemStruct(..) => "struct",
ItemUnion(..) => "union",
ItemTrait(..) => "trait",
ItemImpl(..) => "impl",
ItemDefaultImpl(..) => "default impl",

View file

@ -67,7 +67,6 @@ macro_rules! hir_vec {
pub mod check_attr;
pub mod def;
pub mod def_id;
pub mod fold;
pub mod intravisit;
pub mod lowering;
pub mod map;
@ -469,7 +468,7 @@ impl Pat {
}
match self.node {
PatKind::Binding(_, _, Some(ref p)) => p.walk_(it),
PatKind::Binding(.., Some(ref p)) => p.walk_(it),
PatKind::Struct(_, ref fields, _) => {
fields.iter().all(|field| field.node.pat.walk_(it))
}
@ -486,7 +485,7 @@ impl Pat {
}
PatKind::Wild |
PatKind::Lit(_) |
PatKind::Range(_, _) |
PatKind::Range(..) |
PatKind::Binding(..) |
PatKind::Path(..) => {
true
@ -1483,6 +1482,8 @@ pub enum Item_ {
ItemEnum(EnumDef, Generics),
/// A struct definition, e.g. `struct Foo<A> {x: A}`
ItemStruct(VariantData, Generics),
/// A union definition, e.g. `union Foo<A, B> {x: A, y: B}`
ItemUnion(VariantData, Generics),
/// Represents a Trait Declaration
ItemTrait(Unsafety, Generics, TyParamBounds, HirVec<TraitItem>),
@ -1512,6 +1513,7 @@ impl Item_ {
ItemTy(..) => "type alias",
ItemEnum(..) => "enum",
ItemStruct(..) => "struct",
ItemUnion(..) => "union",
ItemTrait(..) => "trait",
ItemImpl(..) |
ItemDefaultImpl(..) => "item",

View file

@ -53,7 +53,7 @@ impl<T: ExactSizeIterator> EnumerateAndAdjustIterator for T {
pub fn pat_is_refutable(dm: &DefMap, pat: &hir::Pat) -> bool {
match pat.node {
PatKind::Lit(_) | PatKind::Range(_, _) | PatKind::Path(Some(..), _) => true,
PatKind::Lit(_) | PatKind::Range(..) | PatKind::Path(Some(..), _) => true,
PatKind::TupleStruct(..) |
PatKind::Path(..) |
PatKind::Struct(..) => {
@ -62,7 +62,7 @@ pub fn pat_is_refutable(dm: &DefMap, pat: &hir::Pat) -> bool {
_ => false
}
}
PatKind::Vec(_, _, _) => true,
PatKind::Vec(..) => true,
_ => false
}
}
@ -174,7 +174,7 @@ pub fn necessary_variants(dm: &DefMap, pat: &hir::Pat) -> Vec<DefId> {
PatKind::Path(..) |
PatKind::Struct(..) => {
match dm.get(&p.id) {
Some(&PathResolution { base_def: Def::Variant(_, id), .. }) => {
Some(&PathResolution { base_def: Def::Variant(id), .. }) => {
variants.push(id);
}
_ => ()

View file

@ -752,7 +752,10 @@ impl<'a> State<'a> {
self.head(&visibility_qualified(&item.vis, "struct"))?;
self.print_struct(struct_def, generics, item.name, item.span, true)?;
}
hir::ItemUnion(ref struct_def, ref generics) => {
self.head(&visibility_qualified(&item.vis, "union"))?;
self.print_struct(struct_def, generics, item.name, item.span, true)?;
}
hir::ItemDefaultImpl(unsafety, ref trait_ref) => {
self.head("")?;
self.print_visibility(&item.vis)?;
@ -1753,9 +1756,9 @@ impl<'a> State<'a> {
self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(&p))?;
}
} else {
try!(self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(&p)));
self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(&p))?;
}
try!(self.pclose());
self.pclose()?;
}
PatKind::Path(None, ref path) => {
self.print_path(path, true, 0)?;

View file

@ -105,6 +105,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
match item.node {
hir::ItemImpl(..) => "impl",
hir::ItemStruct(..) => "struct",
hir::ItemUnion(..) => "union",
hir::ItemEnum(..) => "enum",
hir::ItemTrait(..) => "trait",
hir::ItemFn(..) => "function body",
@ -139,9 +140,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
Some(ast_map::NodeExpr(expr)) => match expr.node {
hir::ExprCall(..) => "call",
hir::ExprMethodCall(..) => "method call",
hir::ExprMatch(_, _, hir::MatchSource::IfLetDesugar { .. }) => "if let",
hir::ExprMatch(_, _, hir::MatchSource::WhileLetDesugar) => "while let",
hir::ExprMatch(_, _, hir::MatchSource::ForLoopDesugar) => "for",
hir::ExprMatch(.., hir::MatchSource::IfLetDesugar { .. }) => "if let",
hir::ExprMatch(.., hir::MatchSource::WhileLetDesugar) => "while let",
hir::ExprMatch(.., hir::MatchSource::ForLoopDesugar) => "for",
hir::ExprMatch(..) => "match",
_ => "expression",
},
@ -487,10 +488,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
// if they are both "path types", there's a chance of ambiguity
// due to different versions of the same crate
match (&exp_found.expected.sty, &exp_found.found.sty) {
(&ty::TyEnum(ref exp_adt, _), &ty::TyEnum(ref found_adt, _)) |
(&ty::TyStruct(ref exp_adt, _), &ty::TyStruct(ref found_adt, _)) |
(&ty::TyEnum(ref exp_adt, _), &ty::TyStruct(ref found_adt, _)) |
(&ty::TyStruct(ref exp_adt, _), &ty::TyEnum(ref found_adt, _)) => {
(&ty::TyAdt(exp_adt, _), &ty::TyAdt(found_adt, _)) => {
report_path_match(err, exp_adt.did, found_adt.did);
},
_ => ()
@ -549,7 +547,18 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
};
if !is_simple_error {
diag.note_expected_found(&"type", &expected, &found);
if expected == found {
if let &TypeError::Sorts(ref values) = terr {
diag.note_expected_found_extra(
&"type", &expected, &found,
&format!(" ({})", values.expected.sort_string(self.tcx)),
&format!(" ({})", values.found.sort_string(self.tcx)));
} else {
diag.note_expected_found(&"type", &expected, &found);
}
} else {
diag.note_expected_found(&"type", &expected, &found);
}
}
}
@ -1370,7 +1379,8 @@ impl<'a, 'gcx, 'tcx> Rebuilder<'a, 'gcx, 'tcx> {
}
hir::TyPath(ref maybe_qself, ref path) => {
match self.tcx.expect_def(cur_ty.id) {
Def::Enum(did) | Def::TyAlias(did) | Def::Struct(did) => {
Def::Enum(did) | Def::TyAlias(did) |
Def::Struct(did) | Def::Union(did) => {
let generics = self.tcx.lookup_generics(did);
let expected =
@ -1785,7 +1795,7 @@ fn lifetimes_in_scope<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
let method_id_opt = match tcx.map.find(parent) {
Some(node) => match node {
ast_map::NodeItem(item) => match item.node {
hir::ItemFn(_, _, _, _, ref gen, _) => {
hir::ItemFn(.., ref gen, _) => {
taken.extend_from_slice(&gen.lifetimes);
None
},
@ -1809,7 +1819,7 @@ fn lifetimes_in_scope<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
if let Some(node) = tcx.map.find(parent) {
match node {
ast_map::NodeItem(item) => match item.node {
hir::ItemImpl(_, _, ref gen, _, _, _) => {
hir::ItemImpl(_, _, ref gen, ..) => {
taken.extend_from_slice(&gen.lifetimes);
}
_ => ()

View file

@ -156,7 +156,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
ty::TyInt(..) |
ty::TyUint(..) |
ty::TyFloat(..) |
ty::TyEnum(..) |
ty::TyAdt(..) |
ty::TyBox(..) |
ty::TyStr |
ty::TyError |
@ -167,7 +167,6 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
ty::TyFnDef(..) |
ty::TyFnPtr(_) |
ty::TyTrait(..) |
ty::TyStruct(..) |
ty::TyClosure(..) |
ty::TyNever |
ty::TyTuple(..) |

View file

@ -130,7 +130,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
debug!("higher_ranked_match: skol_map={:?}", skol_map);
// Equate types now that bound regions have been replaced.
try!(self.equate(a_is_expected).relate(&a_match, &b_match));
self.equate(a_is_expected).relate(&a_match, &b_match)?;
// Map each skolemized region to a vector of other regions that it
// must be equated with. (Note that this vector may include other
@ -684,7 +684,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
warnings.extend(
match self.region_vars.var_origin(vid) {
LateBoundRegion(_,
ty::BrNamed(_, _, wc),
ty::BrNamed(.., wc),
_) => Some(wc),
_ => None,
});

View file

@ -136,13 +136,6 @@ pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
// avoid reporting the same error twice.
pub reported_trait_errors: RefCell<FnvHashSet<traits::TraitErrorKey<'tcx>>>,
// This is a temporary field used for toggling on normalization in the inference context,
// as we move towards the approach described here:
// https://internals.rust-lang.org/t/flattening-the-contexts-for-fun-and-profit/2293
// At a point sometime in the future normalization will be done by the typing context
// directly.
normalize: bool,
// Sadly, the behavior of projection varies a bit depending on the
// stage of compilation. The specifics are given in the
// documentation for `Reveal`.
@ -232,7 +225,7 @@ impl TypeOrigin {
&TypeOrigin::RelateOutputImplTypes(_) |
&TypeOrigin::ExprAssignable(_) => "mismatched types",
&TypeOrigin::MethodCompatCheck(_) => "method not compatible with trait",
&TypeOrigin::MatchExpressionArm(_, _, source) => match source {
&TypeOrigin::MatchExpressionArm(.., source) => match source {
hir::MatchSource::IfLetDesugar{..} => "`if let` arms have incompatible types",
_ => "match arms have incompatible types",
},
@ -255,7 +248,7 @@ impl TypeOrigin {
&TypeOrigin::RelateOutputImplTypes(_) => {
"trait type parameters matches those specified on the impl"
}
&TypeOrigin::MatchExpressionArm(_, _, _) => "match arms have compatible types",
&TypeOrigin::MatchExpressionArm(..) => "match arms have compatible types",
&TypeOrigin::IfExpression(_) => "if and else have compatible types",
&TypeOrigin::IfExpressionWithNoElse(_) => "if missing an else returns ()",
&TypeOrigin::RangeExpression(_) => "start and end of range have compatible types",
@ -458,7 +451,6 @@ pub struct InferCtxtBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
tables: Option<RefCell<ty::Tables<'tcx>>>,
param_env: Option<ty::ParameterEnvironment<'gcx>>,
projection_mode: Reveal,
normalize: bool
}
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
@ -473,19 +465,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
tables: tables.map(RefCell::new),
param_env: param_env,
projection_mode: projection_mode,
normalize: false
}
}
pub fn normalizing_infer_ctxt(self, projection_mode: Reveal)
-> InferCtxtBuilder<'a, 'gcx, 'tcx> {
InferCtxtBuilder {
global_tcx: self,
arenas: ty::CtxtArenas::new(),
tables: None,
param_env: None,
projection_mode: projection_mode,
normalize: false
}
}
@ -506,7 +485,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
evaluation_cache: traits::EvaluationCache::new(),
projection_cache: RefCell::new(traits::ProjectionCache::new()),
reported_trait_errors: RefCell::new(FnvHashSet()),
normalize: false,
projection_mode: Reveal::NotSpecializable,
tainted_by_errors_flag: Cell::new(false),
err_count_on_creation: self.sess.err_count(),
@ -525,7 +503,6 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> {
ref tables,
ref mut param_env,
projection_mode,
normalize
} = *self;
let tables = if let Some(ref tables) = *tables {
InferTables::Local(tables)
@ -547,7 +524,6 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> {
selection_cache: traits::SelectionCache::new(),
evaluation_cache: traits::EvaluationCache::new(),
reported_trait_errors: RefCell::new(FnvHashSet()),
normalize: normalize,
projection_mode: projection_mode,
tainted_by_errors_flag: Cell::new(false),
err_count_on_creation: tcx.sess.err_count(),
@ -683,6 +659,15 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
self.drain_fulfillment_cx_or_panic(DUMMY_SP, &mut fulfill_cx, &result)
}
/// Finishes processes any obligations that remain in the
/// fulfillment context, and then returns the result with all type
/// variables removed and regions erased. Because this is intended
/// for use after type-check has completed, if any errors occur,
/// it will panic. It is used during normalization and other cases
/// where processing the obligations in `fulfill_cx` may cause
/// type inference variables that appear in `result` to be
/// unified, and hence we need to process those obligations to get
/// the complete picture of the type.
pub fn drain_fulfillment_cx_or_panic<T>(&self,
span: Span,
fulfill_cx: &mut traits::FulfillmentContext<'tcx>,
@ -692,45 +677,26 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
{
debug!("drain_fulfillment_cx_or_panic()");
let when = "resolving bounds after type-checking";
let v = match self.drain_fulfillment_cx(fulfill_cx, result) {
Ok(v) => v,
Err(errors) => {
span_bug!(span, "Encountered errors `{:?}` {}", errors, when);
}
};
match self.tcx.lift_to_global(&v) {
Some(v) => v,
None => {
span_bug!(span, "Uninferred types/regions in `{:?}` {}", v, when);
}
}
}
/// Finishes processes any obligations that remain in the fulfillment
/// context, and then "freshens" and returns `result`. This is
/// primarily used during normalization and other cases where
/// processing the obligations in `fulfill_cx` may cause type
/// inference variables that appear in `result` to be unified, and
/// hence we need to process those obligations to get the complete
/// picture of the type.
pub fn drain_fulfillment_cx<T>(&self,
fulfill_cx: &mut traits::FulfillmentContext<'tcx>,
result: &T)
-> Result<T,Vec<traits::FulfillmentError<'tcx>>>
where T : TypeFoldable<'tcx>
{
debug!("drain_fulfillment_cx(result={:?})",
result);
// In principle, we only need to do this so long as `result`
// contains unbound type parameters. It could be a slight
// optimization to stop iterating early.
fulfill_cx.select_all_or_error(self)?;
match fulfill_cx.select_all_or_error(self) {
Ok(()) => { }
Err(errors) => {
span_bug!(span, "Encountered errors `{:?}` resolving bounds after type-checking",
errors);
}
}
let result = self.resolve_type_vars_if_possible(result);
Ok(self.tcx.erase_regions(&result))
let result = self.tcx.erase_regions(&result);
match self.tcx.lift_to_global(&result) {
Some(result) => result,
None => {
span_bug!(span, "Uninferred types/regions in `{:?}`", result);
}
}
}
pub fn projection_mode(&self) -> Reveal {
@ -864,6 +830,33 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
result.map(move |t| InferOk { value: t, obligations: fields.obligations })
}
// Clear the "obligations in snapshot" flag, invoke the closure,
// then restore the flag to its original value. This flag is a
// debugging measure designed to detect cases where we start a
// snapshot, create type variables, register obligations involving
// those type variables in the fulfillment cx, and then have to
// unroll the snapshot, leaving "dangling type variables" behind.
// In such cases, the flag will be set by the fulfillment cx, and
// an assertion will fail when rolling the snapshot back. Very
// useful, much better than grovelling through megabytes of
// RUST_LOG output.
//
// HOWEVER, in some cases the flag is wrong. In particular, we
// sometimes create a "mini-fulfilment-cx" in which we enroll
// obligations. As long as this fulfillment cx is fully drained
// before we return, this is not a problem, as there won't be any
// escaping obligations in the main cx. In those cases, you can
// use this function.
pub fn save_and_restore_obligations_in_snapshot_flag<F, R>(&self, func: F) -> R
where F: FnOnce(&Self) -> R
{
let flag = self.obligations_in_snapshot.get();
self.obligations_in_snapshot.set(false);
let result = func(self);
self.obligations_in_snapshot.set(flag);
result
}
fn start_snapshot(&self) -> CombinedSnapshot {
debug!("start_snapshot()");
@ -1702,17 +1695,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
}
let closure_ty = self.tcx.closure_type(def_id, substs);
if self.normalize {
let closure_ty = self.tcx.erase_regions(&closure_ty);
if !closure_ty.has_projection_types() {
return closure_ty;
}
self.normalize_projections_in(&closure_ty)
} else {
closure_ty
}
closure_ty
}
}
@ -1756,7 +1739,7 @@ impl TypeOrigin {
TypeOrigin::ExprAssignable(span) => span,
TypeOrigin::Misc(span) => span,
TypeOrigin::RelateOutputImplTypes(span) => span,
TypeOrigin::MatchExpressionArm(match_span, _, _) => match_span,
TypeOrigin::MatchExpressionArm(match_span, ..) => match_span,
TypeOrigin::IfExpression(span) => span,
TypeOrigin::IfExpressionWithNoElse(span) => span,
TypeOrigin::RangeExpression(span) => span,
@ -1809,7 +1792,7 @@ impl RegionVariableOrigin {
Autoref(a) => a,
Coercion(a) => a,
EarlyBoundRegion(a, _) => a,
LateBoundRegion(a, _, _) => a,
LateBoundRegion(a, ..) => a,
BoundRegionInCoherence(_) => syntax_pos::DUMMY_SP,
UpvarRegion(_, a) => a
}

View file

@ -63,9 +63,8 @@ pub fn maybe_print_constraints_for<'a, 'gcx, 'tcx>(
return;
}
let requested_node: Option<ast::NodeId> = env::var("RUST_REGION_GRAPH_NODE")
.ok()
.and_then(|s| s.parse().ok());
let requested_node = env::var("RUST_REGION_GRAPH_NODE")
.ok().and_then(|s| s.parse().map(ast::NodeId::new).ok());
if requested_node.is_some() && requested_node != Some(subject_node) {
return;

View file

@ -605,7 +605,7 @@ impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> {
undo_entry: &UndoLogEntry<'tcx>)
-> bool {
match undo_entry {
&AddConstraint(ConstrainVarSubVar(_, _)) =>
&AddConstraint(ConstrainVarSubVar(..)) =>
false,
&AddConstraint(ConstrainRegSubVar(a, _)) =>
skols.contains(&a),
@ -613,7 +613,7 @@ impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> {
skols.contains(&b),
&AddConstraint(ConstrainRegSubReg(a, b)) =>
skols.contains(&a) || skols.contains(&b),
&AddGiven(_, _) =>
&AddGiven(..) =>
false,
&AddVerify(_) =>
false,
@ -1372,7 +1372,7 @@ impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> {
(&ReFree(..), &ReFree(..)) => Equal,
(&ReFree(..), _) => Less,
(_, &ReFree(..)) => Greater,
(_, _) => Equal,
(..) => Equal,
}
}
lower_bounds.sort_by(|a, b| free_regions_first(a, b));

Some files were not shown because too many files have changed in this diff Show more