Merge branch 'master' into stabilise/termination-test
This commit is contained in:
commit
72f2f1935d
@ -279,6 +279,9 @@
|
||||
# Whether or not `panic!`s generate backtraces (RUST_BACKTRACE)
|
||||
#backtrace = true
|
||||
|
||||
# Whether to always use incremental compilation when building rustc
|
||||
#incremental = false
|
||||
|
||||
# Build rustc with experimental parallelization
|
||||
#experimental-parallel-queries = false
|
||||
|
||||
|
@ -268,6 +268,15 @@ fn main() {
|
||||
if let Ok(host_linker) = env::var("RUSTC_HOST_LINKER") {
|
||||
cmd.arg(format!("-Clinker={}", host_linker));
|
||||
}
|
||||
|
||||
if let Ok(s) = env::var("RUSTC_HOST_CRT_STATIC") {
|
||||
if s == "true" {
|
||||
cmd.arg("-C").arg("target-feature=+crt-static");
|
||||
}
|
||||
if s == "false" {
|
||||
cmd.arg("-C").arg("target-feature=-crt-static");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if env::var_os("RUSTC_PARALLEL_QUERIES").is_some() {
|
||||
|
@ -489,7 +489,7 @@ class RustBuild(object):
|
||||
"""
|
||||
return os.path.join(self.build_dir, self.build, "stage0")
|
||||
|
||||
def get_toml(self, key):
|
||||
def get_toml(self, key, section=None):
|
||||
"""Returns the value of the given key in config.toml, otherwise returns None
|
||||
|
||||
>>> rb = RustBuild()
|
||||
@ -501,12 +501,29 @@ class RustBuild(object):
|
||||
|
||||
>>> rb.get_toml("key3") is None
|
||||
True
|
||||
|
||||
Optionally also matches the section the key appears in
|
||||
|
||||
>>> rb.config_toml = '[a]\\nkey = "value1"\\n[b]\\nkey = "value2"'
|
||||
>>> rb.get_toml('key', 'a')
|
||||
'value1'
|
||||
>>> rb.get_toml('key', 'b')
|
||||
'value2'
|
||||
>>> rb.get_toml('key', 'c') is None
|
||||
True
|
||||
"""
|
||||
|
||||
cur_section = None
|
||||
for line in self.config_toml.splitlines():
|
||||
section_match = re.match(r'^\s*\[(.*)\]\s*$', line)
|
||||
if section_match is not None:
|
||||
cur_section = section_match.group(1)
|
||||
|
||||
match = re.match(r'^{}\s*=(.*)$'.format(key), line)
|
||||
if match is not None:
|
||||
value = match.group(1)
|
||||
return self.get_string(value) or value.strip()
|
||||
if section is None or section == cur_section:
|
||||
return self.get_string(value) or value.strip()
|
||||
return None
|
||||
|
||||
def cargo(self):
|
||||
@ -589,7 +606,17 @@ class RustBuild(object):
|
||||
env["LIBRARY_PATH"] = os.path.join(self.bin_root(), "lib") + \
|
||||
(os.pathsep + env["LIBRARY_PATH"]) \
|
||||
if "LIBRARY_PATH" in env else ""
|
||||
env["RUSTFLAGS"] = "-Cdebuginfo=2"
|
||||
env["RUSTFLAGS"] = "-Cdebuginfo=2 "
|
||||
|
||||
build_section = "target.{}".format(self.build_triple())
|
||||
target_features = []
|
||||
if self.get_toml("crt-static", build_section) == "true":
|
||||
target_features += ["+crt-static"]
|
||||
elif self.get_toml("crt-static", build_section) == "false":
|
||||
target_features += ["-crt-static"]
|
||||
if target_features:
|
||||
env["RUSTFLAGS"] += "-C target-feature=" + (",".join(target_features)) + " "
|
||||
|
||||
env["PATH"] = os.path.join(self.bin_root(), "bin") + \
|
||||
os.pathsep + env["PATH"]
|
||||
if not os.path.isfile(self.cargo()):
|
||||
|
@ -698,9 +698,14 @@ impl<'a> Builder<'a> {
|
||||
let out_dir = self.stage_out(compiler, mode);
|
||||
cargo
|
||||
.env("CARGO_TARGET_DIR", out_dir)
|
||||
.arg(cmd)
|
||||
.arg("--target")
|
||||
.arg(target);
|
||||
.arg(cmd);
|
||||
|
||||
if cmd != "install" {
|
||||
cargo.arg("--target")
|
||||
.arg(target);
|
||||
} else {
|
||||
assert_eq!(target, compiler.host);
|
||||
}
|
||||
|
||||
// Set a flag for `check` so that certain build scripts can do less work
|
||||
// (e.g. not building/requiring LLVM).
|
||||
@ -801,7 +806,7 @@ impl<'a> Builder<'a> {
|
||||
);
|
||||
}
|
||||
|
||||
if mode == Mode::Tool {
|
||||
if mode.is_tool() {
|
||||
// Tools like cargo and rls don't get debuginfo by default right now, but this can be
|
||||
// enabled in the config. Adding debuginfo makes them several times larger.
|
||||
if self.config.rust_debuginfo_tools {
|
||||
@ -842,6 +847,10 @@ impl<'a> Builder<'a> {
|
||||
cargo.env("RUSTC_CRT_STATIC", x.to_string());
|
||||
}
|
||||
|
||||
if let Some(x) = self.crt_static(compiler.host) {
|
||||
cargo.env("RUSTC_HOST_CRT_STATIC", x.to_string());
|
||||
}
|
||||
|
||||
// Enable usage of unstable features
|
||||
cargo.env("RUSTC_BOOTSTRAP", "1");
|
||||
self.add_rust_test_threads(&mut cargo);
|
||||
@ -862,7 +871,7 @@ impl<'a> Builder<'a> {
|
||||
//
|
||||
// If LLVM support is disabled we need to use the snapshot compiler to compile
|
||||
// build scripts, as the new compiler doesn't support executables.
|
||||
if mode == Mode::Libstd || !self.config.llvm_enabled {
|
||||
if mode == Mode::Std || !self.config.llvm_enabled {
|
||||
cargo
|
||||
.env("RUSTC_SNAPSHOT", &self.initial_rustc)
|
||||
.env("RUSTC_SNAPSHOT_LIBDIR", self.rustc_snapshot_libdir());
|
||||
@ -894,7 +903,7 @@ impl<'a> Builder<'a> {
|
||||
cargo.env("RUSTC_VERBOSE", format!("{}", self.verbosity));
|
||||
|
||||
// in std, we want to avoid denying warnings for stage 0 as that makes cfg's painful.
|
||||
if self.config.deny_warnings && !(mode == Mode::Libstd && stage == 0) {
|
||||
if self.config.deny_warnings && !(mode == Mode::Std && stage == 0) {
|
||||
cargo.env("RUSTC_DENY_WARNINGS", "1");
|
||||
}
|
||||
|
||||
@ -954,7 +963,7 @@ impl<'a> Builder<'a> {
|
||||
}
|
||||
|
||||
if cmd == "build"
|
||||
&& mode == Mode::Libstd
|
||||
&& mode == Mode::Std
|
||||
&& self.config.extended
|
||||
&& compiler.is_final_stage(self)
|
||||
{
|
||||
@ -1003,7 +1012,7 @@ impl<'a> Builder<'a> {
|
||||
// be resolved because MinGW has the import library. The downside is we
|
||||
// don't get newer functions from Windows, but we don't use any of them
|
||||
// anyway.
|
||||
if mode != Mode::Tool {
|
||||
if !mode.is_tool() {
|
||||
cargo.env("WINAPI_NO_BUNDLED_LIBRARIES", "1");
|
||||
}
|
||||
|
||||
@ -1018,8 +1027,8 @@ impl<'a> Builder<'a> {
|
||||
}
|
||||
|
||||
if self.config.rust_optimize {
|
||||
// FIXME: cargo bench does not accept `--release`
|
||||
if cmd != "bench" {
|
||||
// FIXME: cargo bench/install do not accept `--release`
|
||||
if cmd != "bench" && cmd != "install" {
|
||||
cargo.arg("--release");
|
||||
}
|
||||
}
|
||||
@ -1742,7 +1751,7 @@ mod __test {
|
||||
&[test::Crate {
|
||||
compiler: Compiler { host, stage: 0 },
|
||||
target: host,
|
||||
mode: Mode::Libstd,
|
||||
mode: Mode::Std,
|
||||
test_kind: test::TestKind::Test,
|
||||
krate: INTERNER.intern_str("std"),
|
||||
},]
|
||||
|
@ -40,10 +40,10 @@ impl Step for Std {
|
||||
let target = self.target;
|
||||
let compiler = builder.compiler(0, builder.config.build);
|
||||
|
||||
let out_dir = builder.stage_out(compiler, Mode::Libstd);
|
||||
let out_dir = builder.stage_out(compiler, Mode::Std);
|
||||
builder.clear_if_dirty(&out_dir, &builder.rustc(compiler));
|
||||
|
||||
let mut cargo = builder.cargo(compiler, Mode::Libstd, target, "check");
|
||||
let mut cargo = builder.cargo(compiler, Mode::Std, target, "check");
|
||||
std_cargo(builder, &compiler, target, &mut cargo);
|
||||
|
||||
let _folder = builder.fold_output(|| format!("stage{}-std", compiler.stage));
|
||||
@ -87,11 +87,11 @@ impl Step for Rustc {
|
||||
let compiler = builder.compiler(0, builder.config.build);
|
||||
let target = self.target;
|
||||
|
||||
let stage_out = builder.stage_out(compiler, Mode::Librustc);
|
||||
let stage_out = builder.stage_out(compiler, Mode::Rustc);
|
||||
builder.clear_if_dirty(&stage_out, &libstd_stamp(builder, compiler, target));
|
||||
builder.clear_if_dirty(&stage_out, &libtest_stamp(builder, compiler, target));
|
||||
|
||||
let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "check");
|
||||
let mut cargo = builder.cargo(compiler, Mode::Rustc, target, "check");
|
||||
rustc_cargo(builder, &mut cargo);
|
||||
|
||||
let _folder = builder.fold_output(|| format!("stage{}-rustc", compiler.stage));
|
||||
@ -137,7 +137,7 @@ impl Step for CodegenBackend {
|
||||
let target = self.target;
|
||||
let backend = self.backend;
|
||||
|
||||
let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "check");
|
||||
let mut cargo = builder.cargo(compiler, Mode::Codegen, target, "check");
|
||||
let features = builder.rustc_features().to_string();
|
||||
cargo.arg("--manifest-path").arg(builder.src.join("src/librustc_codegen_llvm/Cargo.toml"));
|
||||
rustc_cargo_env(builder, &mut cargo);
|
||||
@ -175,10 +175,10 @@ impl Step for Test {
|
||||
let compiler = builder.compiler(0, builder.config.build);
|
||||
let target = self.target;
|
||||
|
||||
let out_dir = builder.stage_out(compiler, Mode::Libtest);
|
||||
let out_dir = builder.stage_out(compiler, Mode::Test);
|
||||
builder.clear_if_dirty(&out_dir, &libstd_stamp(builder, compiler, target));
|
||||
|
||||
let mut cargo = builder.cargo(compiler, Mode::Libtest, target, "check");
|
||||
let mut cargo = builder.cargo(compiler, Mode::Test, target, "check");
|
||||
test_cargo(builder, &compiler, target, &mut cargo);
|
||||
|
||||
let _folder = builder.fold_output(|| format!("stage{}-test", compiler.stage));
|
||||
@ -219,6 +219,7 @@ impl Step for Rustdoc {
|
||||
|
||||
let mut cargo = prepare_tool_cargo(builder,
|
||||
compiler,
|
||||
Mode::ToolRustc,
|
||||
target,
|
||||
"check",
|
||||
"src/tools/rustdoc");
|
||||
@ -236,7 +237,7 @@ impl Step for Rustdoc {
|
||||
builder.ensure(tool::CleanTools {
|
||||
compiler,
|
||||
target,
|
||||
mode: Mode::Tool,
|
||||
cause: Mode::Rustc,
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -244,19 +245,19 @@ impl Step for Rustdoc {
|
||||
/// Cargo's output path for the standard library in a given stage, compiled
|
||||
/// by a particular compiler for the specified target.
|
||||
pub fn libstd_stamp(builder: &Builder, compiler: Compiler, target: Interned<String>) -> PathBuf {
|
||||
builder.cargo_out(compiler, Mode::Libstd, target).join(".libstd-check.stamp")
|
||||
builder.cargo_out(compiler, Mode::Std, target).join(".libstd-check.stamp")
|
||||
}
|
||||
|
||||
/// Cargo's output path for libtest in a given stage, compiled by a particular
|
||||
/// compiler for the specified target.
|
||||
pub fn libtest_stamp(builder: &Builder, compiler: Compiler, target: Interned<String>) -> PathBuf {
|
||||
builder.cargo_out(compiler, Mode::Libtest, target).join(".libtest-check.stamp")
|
||||
builder.cargo_out(compiler, Mode::Test, target).join(".libtest-check.stamp")
|
||||
}
|
||||
|
||||
/// Cargo's output path for librustc in a given stage, compiled by a particular
|
||||
/// compiler for the specified target.
|
||||
pub fn librustc_stamp(builder: &Builder, compiler: Compiler, target: Interned<String>) -> PathBuf {
|
||||
builder.cargo_out(compiler, Mode::Librustc, target).join(".librustc-check.stamp")
|
||||
builder.cargo_out(compiler, Mode::Rustc, target).join(".librustc-check.stamp")
|
||||
}
|
||||
|
||||
/// Cargo's output path for librustc_codegen_llvm in a given stage, compiled by a particular
|
||||
@ -265,12 +266,12 @@ fn codegen_backend_stamp(builder: &Builder,
|
||||
compiler: Compiler,
|
||||
target: Interned<String>,
|
||||
backend: Interned<String>) -> PathBuf {
|
||||
builder.cargo_out(compiler, Mode::Librustc, target)
|
||||
builder.cargo_out(compiler, Mode::Codegen, target)
|
||||
.join(format!(".librustc_codegen_llvm-{}-check.stamp", backend))
|
||||
}
|
||||
|
||||
/// Cargo's output path for rustdoc in a given stage, compiled by a particular
|
||||
/// compiler for the specified target.
|
||||
pub fn rustdoc_stamp(builder: &Builder, compiler: Compiler, target: Interned<String>) -> PathBuf {
|
||||
builder.cargo_out(compiler, Mode::Tool, target).join(".rustdoc-check.stamp")
|
||||
builder.cargo_out(compiler, Mode::ToolRustc, target).join(".rustdoc-check.stamp")
|
||||
}
|
||||
|
@ -98,9 +98,9 @@ impl Step for Std {
|
||||
copy_musl_third_party_objects(builder, target, &libdir);
|
||||
}
|
||||
|
||||
let out_dir = builder.cargo_out(compiler, Mode::Libstd, target);
|
||||
let out_dir = builder.cargo_out(compiler, Mode::Std, target);
|
||||
builder.clear_if_dirty(&out_dir, &builder.rustc(compiler));
|
||||
let mut cargo = builder.cargo(compiler, Mode::Libstd, target, "build");
|
||||
let mut cargo = builder.cargo(compiler, Mode::Std, target, "build");
|
||||
std_cargo(builder, &compiler, target, &mut cargo);
|
||||
|
||||
let _folder = builder.fold_output(|| format!("stage{}-std", compiler.stage));
|
||||
@ -240,7 +240,7 @@ impl Step for StdLink {
|
||||
builder.ensure(tool::CleanTools {
|
||||
compiler: target_compiler,
|
||||
target,
|
||||
mode: Mode::Libstd,
|
||||
cause: Mode::Std,
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -368,9 +368,9 @@ impl Step for Test {
|
||||
return;
|
||||
}
|
||||
|
||||
let out_dir = builder.cargo_out(compiler, Mode::Libtest, target);
|
||||
let out_dir = builder.cargo_out(compiler, Mode::Test, target);
|
||||
builder.clear_if_dirty(&out_dir, &libstd_stamp(builder, compiler, target));
|
||||
let mut cargo = builder.cargo(compiler, Mode::Libtest, target, "build");
|
||||
let mut cargo = builder.cargo(compiler, Mode::Test, target, "build");
|
||||
test_cargo(builder, &compiler, target, &mut cargo);
|
||||
|
||||
let _folder = builder.fold_output(|| format!("stage{}-test", compiler.stage));
|
||||
@ -431,7 +431,7 @@ impl Step for TestLink {
|
||||
builder.ensure(tool::CleanTools {
|
||||
compiler: target_compiler,
|
||||
target,
|
||||
mode: Mode::Libtest,
|
||||
cause: Mode::Test,
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -489,11 +489,11 @@ impl Step for Rustc {
|
||||
compiler: builder.compiler(self.compiler.stage, builder.config.build),
|
||||
target: builder.config.build,
|
||||
});
|
||||
let cargo_out = builder.cargo_out(compiler, Mode::Librustc, target);
|
||||
let cargo_out = builder.cargo_out(compiler, Mode::Rustc, target);
|
||||
builder.clear_if_dirty(&cargo_out, &libstd_stamp(builder, compiler, target));
|
||||
builder.clear_if_dirty(&cargo_out, &libtest_stamp(builder, compiler, target));
|
||||
|
||||
let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "build");
|
||||
let mut cargo = builder.cargo(compiler, Mode::Rustc, target, "build");
|
||||
rustc_cargo(builder, &mut cargo);
|
||||
|
||||
let _folder = builder.fold_output(|| format!("stage{}-rustc", compiler.stage));
|
||||
@ -585,7 +585,7 @@ impl Step for RustcLink {
|
||||
builder.ensure(tool::CleanTools {
|
||||
compiler: target_compiler,
|
||||
target,
|
||||
mode: Mode::Librustc,
|
||||
cause: Mode::Rustc,
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -634,7 +634,7 @@ impl Step for CodegenBackend {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "build");
|
||||
let mut cargo = builder.cargo(compiler, Mode::Codegen, target, "build");
|
||||
let mut features = builder.rustc_features().to_string();
|
||||
cargo.arg("--manifest-path")
|
||||
.arg(builder.src.join("src/librustc_codegen_llvm/Cargo.toml"));
|
||||
@ -642,7 +642,7 @@ impl Step for CodegenBackend {
|
||||
|
||||
features += &build_codegen_backend(&builder, &mut cargo, &compiler, target, backend);
|
||||
|
||||
let tmp_stamp = builder.cargo_out(compiler, Mode::Librustc, target)
|
||||
let tmp_stamp = builder.cargo_out(compiler, Mode::Codegen, target)
|
||||
.join(".tmp.stamp");
|
||||
|
||||
let _folder = builder.fold_output(|| format!("stage{}-rustc_codegen_llvm", compiler.stage));
|
||||
@ -793,19 +793,19 @@ fn copy_lld_to_sysroot(builder: &Builder,
|
||||
/// Cargo's output path for the standard library in a given stage, compiled
|
||||
/// by a particular compiler for the specified target.
|
||||
pub fn libstd_stamp(builder: &Builder, compiler: Compiler, target: Interned<String>) -> PathBuf {
|
||||
builder.cargo_out(compiler, Mode::Libstd, target).join(".libstd.stamp")
|
||||
builder.cargo_out(compiler, Mode::Std, target).join(".libstd.stamp")
|
||||
}
|
||||
|
||||
/// Cargo's output path for libtest in a given stage, compiled by a particular
|
||||
/// compiler for the specified target.
|
||||
pub fn libtest_stamp(builder: &Builder, compiler: Compiler, target: Interned<String>) -> PathBuf {
|
||||
builder.cargo_out(compiler, Mode::Libtest, target).join(".libtest.stamp")
|
||||
builder.cargo_out(compiler, Mode::Test, target).join(".libtest.stamp")
|
||||
}
|
||||
|
||||
/// Cargo's output path for librustc in a given stage, compiled by a particular
|
||||
/// compiler for the specified target.
|
||||
pub fn librustc_stamp(builder: &Builder, compiler: Compiler, target: Interned<String>) -> PathBuf {
|
||||
builder.cargo_out(compiler, Mode::Librustc, target).join(".librustc.stamp")
|
||||
builder.cargo_out(compiler, Mode::Rustc, target).join(".librustc.stamp")
|
||||
}
|
||||
|
||||
/// Cargo's output path for librustc_codegen_llvm in a given stage, compiled by a particular
|
||||
@ -814,7 +814,7 @@ fn codegen_backend_stamp(builder: &Builder,
|
||||
compiler: Compiler,
|
||||
target: Interned<String>,
|
||||
backend: Interned<String>) -> PathBuf {
|
||||
builder.cargo_out(compiler, Mode::Librustc, target)
|
||||
builder.cargo_out(compiler, Mode::Codegen, target)
|
||||
.join(format!(".librustc_codegen_llvm-{}.stamp", backend))
|
||||
}
|
||||
|
||||
@ -971,7 +971,7 @@ impl Step for Assemble {
|
||||
}
|
||||
|
||||
// Link the compiler binary itself into place
|
||||
let out_dir = builder.cargo_out(build_compiler, Mode::Librustc, host);
|
||||
let out_dir = builder.cargo_out(build_compiler, Mode::Rustc, host);
|
||||
let rustc = out_dir.join(exe("rustc_binary", &*host));
|
||||
let bindir = sysroot.join("bin");
|
||||
t!(fs::create_dir_all(&bindir));
|
||||
|
@ -303,6 +303,7 @@ struct Rust {
|
||||
dist_src: Option<bool>,
|
||||
quiet_tests: Option<bool>,
|
||||
test_miri: Option<bool>,
|
||||
incremental: Option<bool>,
|
||||
save_toolstates: Option<String>,
|
||||
codegen_backends: Option<Vec<String>>,
|
||||
codegen_backends_dir: Option<String>,
|
||||
@ -529,6 +530,10 @@ impl Config {
|
||||
set(&mut config.rust_dist_src, rust.dist_src);
|
||||
set(&mut config.quiet_tests, rust.quiet_tests);
|
||||
set(&mut config.test_miri, rust.test_miri);
|
||||
// in the case "false" is set explicitly, do not overwrite the command line args
|
||||
if let Some(true) = rust.incremental {
|
||||
config.incremental = true;
|
||||
}
|
||||
set(&mut config.wasm_syscall, rust.wasm_syscall);
|
||||
set(&mut config.lld_enabled, rust.lld);
|
||||
config.rustc_parallel_queries = rust.experimental_parallel_queries.unwrap_or(false);
|
||||
|
@ -722,7 +722,7 @@ impl Step for Analysis {
|
||||
|
||||
let image = tmpdir(builder).join(format!("{}-{}-image", name, target));
|
||||
|
||||
let src = builder.stage_out(compiler, Mode::Libstd)
|
||||
let src = builder.stage_out(compiler, Mode::Std)
|
||||
.join(target).join(builder.cargo_dir()).join("deps");
|
||||
|
||||
let image_src = src.join("save-analysis");
|
||||
@ -951,13 +951,16 @@ impl Step for PlainSourceTarball {
|
||||
has_cargo_vendor |= line.starts_with("cargo-vendor ");
|
||||
}
|
||||
if !has_cargo_vendor {
|
||||
let mut cmd = Command::new(&builder.initial_cargo);
|
||||
cmd.arg("install")
|
||||
.arg("--force")
|
||||
let mut cmd = builder.cargo(
|
||||
builder.compiler(0, builder.config.build),
|
||||
Mode::ToolRustc,
|
||||
builder.config.build,
|
||||
"install"
|
||||
);
|
||||
cmd.arg("--force")
|
||||
.arg("--debug")
|
||||
.arg("--vers").arg(CARGO_VENDOR_VERSION)
|
||||
.arg("cargo-vendor")
|
||||
.env("RUSTC", &builder.initial_rustc);
|
||||
.arg("cargo-vendor");
|
||||
if let Some(dir) = builder.openssl_install_dir(builder.config.build) {
|
||||
builder.ensure(native::Openssl {
|
||||
target: builder.config.build,
|
||||
|
@ -463,7 +463,7 @@ impl Step for Std {
|
||||
};
|
||||
|
||||
builder.ensure(compile::Std { compiler, target });
|
||||
let out_dir = builder.stage_out(compiler, Mode::Libstd)
|
||||
let out_dir = builder.stage_out(compiler, Mode::Std)
|
||||
.join(target).join("doc");
|
||||
|
||||
// Here what we're doing is creating a *symlink* (directory junction on
|
||||
@ -483,7 +483,7 @@ impl Step for Std {
|
||||
builder.clear_if_dirty(&my_out, &rustdoc);
|
||||
t!(symlink_dir_force(&builder.config, &my_out, &out_dir));
|
||||
|
||||
let mut cargo = builder.cargo(compiler, Mode::Libstd, target, "doc");
|
||||
let mut cargo = builder.cargo(compiler, Mode::Std, target, "doc");
|
||||
compile::std_cargo(builder, &compiler, target, &mut cargo);
|
||||
|
||||
// Keep a whitelist so we do not build internal stdlib crates, these will be
|
||||
@ -546,7 +546,7 @@ impl Step for Test {
|
||||
builder.ensure(Std { stage, target });
|
||||
|
||||
builder.ensure(compile::Test { compiler, target });
|
||||
let out_dir = builder.stage_out(compiler, Mode::Libtest)
|
||||
let out_dir = builder.stage_out(compiler, Mode::Test)
|
||||
.join(target).join("doc");
|
||||
|
||||
// See docs in std above for why we symlink
|
||||
@ -554,7 +554,7 @@ impl Step for Test {
|
||||
builder.clear_if_dirty(&my_out, &rustdoc);
|
||||
t!(symlink_dir_force(&builder.config, &my_out, &out_dir));
|
||||
|
||||
let mut cargo = builder.cargo(compiler, Mode::Libtest, target, "doc");
|
||||
let mut cargo = builder.cargo(compiler, Mode::Test, target, "doc");
|
||||
compile::test_cargo(builder, &compiler, target, &mut cargo);
|
||||
|
||||
cargo.arg("--no-deps").arg("-p").arg("test");
|
||||
@ -614,7 +614,7 @@ impl Step for WhitelistedRustc {
|
||||
builder.ensure(Std { stage, target });
|
||||
|
||||
builder.ensure(compile::Rustc { compiler, target });
|
||||
let out_dir = builder.stage_out(compiler, Mode::Librustc)
|
||||
let out_dir = builder.stage_out(compiler, Mode::Rustc)
|
||||
.join(target).join("doc");
|
||||
|
||||
// See docs in std above for why we symlink
|
||||
@ -622,7 +622,7 @@ impl Step for WhitelistedRustc {
|
||||
builder.clear_if_dirty(&my_out, &rustdoc);
|
||||
t!(symlink_dir_force(&builder.config, &my_out, &out_dir));
|
||||
|
||||
let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "doc");
|
||||
let mut cargo = builder.cargo(compiler, Mode::Rustc, target, "doc");
|
||||
compile::rustc_cargo(builder, &mut cargo);
|
||||
|
||||
// We don't want to build docs for internal compiler dependencies in this
|
||||
@ -698,12 +698,12 @@ impl Step for Rustc {
|
||||
|
||||
// We do not symlink to the same shared folder that already contains std library
|
||||
// documentation from previous steps as we do not want to include that.
|
||||
let out_dir = builder.stage_out(compiler, Mode::Librustc).join(target).join("doc");
|
||||
let out_dir = builder.stage_out(compiler, Mode::Rustc).join(target).join("doc");
|
||||
builder.clear_if_dirty(&out, &rustdoc);
|
||||
t!(symlink_dir_force(&builder.config, &out, &out_dir));
|
||||
|
||||
// Build cargo command.
|
||||
let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "doc");
|
||||
let mut cargo = builder.cargo(compiler, Mode::Rustc, target, "doc");
|
||||
cargo.env("RUSTDOCFLAGS", "--document-private-items");
|
||||
compile::rustc_cargo(builder, &mut cargo);
|
||||
|
||||
@ -799,13 +799,15 @@ impl Step for Rustdoc {
|
||||
builder.ensure(tool::Rustdoc { host: compiler.host });
|
||||
|
||||
// Symlink compiler docs to the output directory of rustdoc documentation.
|
||||
let out_dir = builder.stage_out(compiler, Mode::Tool).join(target).join("doc");
|
||||
let out_dir = builder.stage_out(compiler, Mode::ToolRustc).join(target).join("doc");
|
||||
t!(fs::create_dir_all(&out_dir));
|
||||
builder.clear_if_dirty(&out, &rustdoc);
|
||||
t!(symlink_dir_force(&builder.config, &out, &out_dir));
|
||||
|
||||
// Build cargo command.
|
||||
let mut cargo = prepare_tool_cargo(builder, compiler, target, "doc", "src/tools/rustdoc");
|
||||
let mut cargo = prepare_tool_cargo(
|
||||
builder, compiler, Mode::ToolRustc, target, "doc", "src/tools/rustdoc");
|
||||
|
||||
cargo.env("RUSTDOCFLAGS", "--document-private-items");
|
||||
builder.run(&mut cargo);
|
||||
}
|
||||
|
@ -307,16 +307,30 @@ impl Crate {
|
||||
#[derive(Debug, Hash, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum Mode {
|
||||
/// Build the standard library, placing output in the "stageN-std" directory.
|
||||
Libstd,
|
||||
Std,
|
||||
|
||||
/// Build libtest, placing output in the "stageN-test" directory.
|
||||
Libtest,
|
||||
Test,
|
||||
|
||||
/// Build librustc and compiler libraries, placing output in the "stageN-rustc" directory.
|
||||
Librustc,
|
||||
/// Build librustc, and compiler libraries, placing output in the "stageN-rustc" directory.
|
||||
Rustc,
|
||||
|
||||
/// Build some tool, placing output in the "stageN-tools" directory.
|
||||
Tool,
|
||||
/// Build codegen libraries, placing output in the "stageN-codegen" directory
|
||||
Codegen,
|
||||
|
||||
/// Build some tools, placing output in the "stageN-tools" directory.
|
||||
ToolStd,
|
||||
ToolTest,
|
||||
ToolRustc,
|
||||
}
|
||||
|
||||
impl Mode {
|
||||
pub fn is_tool(&self) -> bool {
|
||||
match self {
|
||||
Mode::ToolStd | Mode::ToolTest | Mode::ToolRustc => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Build {
|
||||
@ -517,10 +531,11 @@ impl Build {
|
||||
/// The mode indicates what the root directory is for.
|
||||
fn stage_out(&self, compiler: Compiler, mode: Mode) -> PathBuf {
|
||||
let suffix = match mode {
|
||||
Mode::Libstd => "-std",
|
||||
Mode::Libtest => "-test",
|
||||
Mode::Tool => "-tools",
|
||||
Mode::Librustc => "-rustc",
|
||||
Mode::Std => "-std",
|
||||
Mode::Test => "-test",
|
||||
Mode::Codegen => "-rustc",
|
||||
Mode::Rustc => "-rustc",
|
||||
Mode::ToolStd | Mode::ToolTest | Mode::ToolRustc => "-tools",
|
||||
};
|
||||
self.out.join(&*compiler.host)
|
||||
.join(format!("stage{}{}", compiler.stage, suffix))
|
||||
|
@ -222,7 +222,7 @@ impl Step for Cargo {
|
||||
compiler,
|
||||
target: self.host,
|
||||
});
|
||||
let mut cargo = builder.cargo(compiler, Mode::Tool, self.host, "test");
|
||||
let mut cargo = builder.cargo(compiler, Mode::ToolRustc, self.host, "test");
|
||||
cargo
|
||||
.arg("--manifest-path")
|
||||
.arg(builder.src.join("src/tools/cargo/Cargo.toml"));
|
||||
@ -281,7 +281,12 @@ impl Step for Rls {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut cargo = tool::prepare_tool_cargo(builder, compiler, host, "test", "src/tools/rls");
|
||||
let mut cargo = tool::prepare_tool_cargo(builder,
|
||||
compiler,
|
||||
Mode::ToolRustc,
|
||||
host,
|
||||
"test",
|
||||
"src/tools/rls");
|
||||
|
||||
// Don't build tests dynamically, just a pain to work with
|
||||
cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1");
|
||||
@ -331,8 +336,12 @@ impl Step for Rustfmt {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut cargo =
|
||||
tool::prepare_tool_cargo(builder, compiler, host, "test", "src/tools/rustfmt");
|
||||
let mut cargo = tool::prepare_tool_cargo(builder,
|
||||
compiler,
|
||||
Mode::ToolRustc,
|
||||
host,
|
||||
"test",
|
||||
"src/tools/rustfmt");
|
||||
|
||||
// Don't build tests dynamically, just a pain to work with
|
||||
cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1");
|
||||
@ -383,7 +392,7 @@ impl Step for Miri {
|
||||
extra_features: Vec::new(),
|
||||
});
|
||||
if let Some(miri) = miri {
|
||||
let mut cargo = builder.cargo(compiler, Mode::Tool, host, "test");
|
||||
let mut cargo = builder.cargo(compiler, Mode::ToolRustc, host, "test");
|
||||
cargo
|
||||
.arg("--manifest-path")
|
||||
.arg(builder.src.join("src/tools/miri/Cargo.toml"));
|
||||
@ -441,7 +450,7 @@ impl Step for Clippy {
|
||||
extra_features: Vec::new(),
|
||||
});
|
||||
if let Some(clippy) = clippy {
|
||||
let mut cargo = builder.cargo(compiler, Mode::Tool, host, "test");
|
||||
let mut cargo = builder.cargo(compiler, Mode::ToolRustc, host, "test");
|
||||
cargo
|
||||
.arg("--manifest-path")
|
||||
.arg(builder.src.join("src/tools/clippy/Cargo.toml"));
|
||||
@ -453,7 +462,7 @@ impl Step for Clippy {
|
||||
cargo.env("RUSTC_TEST_SUITE", builder.rustc(compiler));
|
||||
cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(compiler));
|
||||
let host_libs = builder
|
||||
.stage_out(compiler, Mode::Tool)
|
||||
.stage_out(compiler, Mode::ToolRustc)
|
||||
.join(builder.cargo_dir());
|
||||
cargo.env("HOST_LIBS", host_libs);
|
||||
// clippy tests need to find the driver
|
||||
@ -952,8 +961,7 @@ impl Step for Compiletest {
|
||||
if suite.ends_with("fulldeps") ||
|
||||
// FIXME: Does pretty need librustc compiled? Note that there are
|
||||
// fulldeps test suites with mode = pretty as well.
|
||||
mode == "pretty" ||
|
||||
mode == "rustdoc"
|
||||
mode == "pretty"
|
||||
{
|
||||
builder.ensure(compile::Rustc { compiler, target });
|
||||
}
|
||||
@ -1435,7 +1443,7 @@ impl Step for CrateLibrustc {
|
||||
builder.ensure(Crate {
|
||||
compiler: self.compiler,
|
||||
target: self.target,
|
||||
mode: Mode::Librustc,
|
||||
mode: Mode::Rustc,
|
||||
test_kind: self.test_kind,
|
||||
krate: self.krate,
|
||||
});
|
||||
@ -1486,7 +1494,7 @@ impl Step for CrateNotDefault {
|
||||
builder.ensure(Crate {
|
||||
compiler: self.compiler,
|
||||
target: self.target,
|
||||
mode: Mode::Libstd,
|
||||
mode: Mode::Std,
|
||||
test_kind: self.test_kind,
|
||||
krate: INTERNER.intern_str(self.krate),
|
||||
});
|
||||
@ -1539,12 +1547,12 @@ impl Step for Crate {
|
||||
|
||||
for krate in builder.in_tree_crates("std") {
|
||||
if run.path.ends_with(&krate.local_path(&builder)) {
|
||||
make(Mode::Libstd, krate);
|
||||
make(Mode::Std, krate);
|
||||
}
|
||||
}
|
||||
for krate in builder.in_tree_crates("test") {
|
||||
if run.path.ends_with(&krate.local_path(&builder)) {
|
||||
make(Mode::Libtest, krate);
|
||||
make(Mode::Test, krate);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1579,13 +1587,13 @@ impl Step for Crate {
|
||||
|
||||
let mut cargo = builder.cargo(compiler, mode, target, test_kind.subcommand());
|
||||
match mode {
|
||||
Mode::Libstd => {
|
||||
Mode::Std => {
|
||||
compile::std_cargo(builder, &compiler, target, &mut cargo);
|
||||
}
|
||||
Mode::Libtest => {
|
||||
Mode::Test => {
|
||||
compile::test_cargo(builder, &compiler, target, &mut cargo);
|
||||
}
|
||||
Mode::Librustc => {
|
||||
Mode::Rustc => {
|
||||
builder.ensure(compile::Rustc { compiler, target });
|
||||
compile::rustc_cargo(builder, &mut cargo);
|
||||
}
|
||||
@ -1719,13 +1727,12 @@ impl Step for CrateRustdoc {
|
||||
let compiler = builder.compiler(builder.top_stage, self.host);
|
||||
let target = compiler.host;
|
||||
|
||||
let mut cargo = tool::prepare_tool_cargo(
|
||||
builder,
|
||||
compiler,
|
||||
target,
|
||||
test_kind.subcommand(),
|
||||
"src/tools/rustdoc",
|
||||
);
|
||||
let mut cargo = tool::prepare_tool_cargo(builder,
|
||||
compiler,
|
||||
Mode::ToolRustc,
|
||||
target,
|
||||
test_kind.subcommand(),
|
||||
"src/tools/rustdoc");
|
||||
if test_kind.subcommand() == "test" && !builder.fail_fast {
|
||||
cargo.arg("--no-fail-fast");
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ use toolstate::ToolState;
|
||||
pub struct CleanTools {
|
||||
pub compiler: Compiler,
|
||||
pub target: Interned<String>,
|
||||
pub mode: Mode,
|
||||
pub cause: Mode,
|
||||
}
|
||||
|
||||
impl Step for CleanTools {
|
||||
@ -41,23 +41,23 @@ impl Step for CleanTools {
|
||||
fn run(self, builder: &Builder) {
|
||||
let compiler = self.compiler;
|
||||
let target = self.target;
|
||||
let mode = self.mode;
|
||||
let cause = self.cause;
|
||||
|
||||
// This is for the original compiler, but if we're forced to use stage 1, then
|
||||
// std/test/rustc stamps won't exist in stage 2, so we need to get those from stage 1, since
|
||||
// we copy the libs forward.
|
||||
let tools_dir = builder.stage_out(compiler, Mode::Tool);
|
||||
let tools_dir = builder.stage_out(compiler, Mode::ToolRustc);
|
||||
let compiler = if builder.force_use_stage1(compiler, target) {
|
||||
builder.compiler(1, compiler.host)
|
||||
} else {
|
||||
compiler
|
||||
};
|
||||
|
||||
for &cur_mode in &[Mode::Libstd, Mode::Libtest, Mode::Librustc] {
|
||||
for &cur_mode in &[Mode::Std, Mode::Test, Mode::Rustc] {
|
||||
let stamp = match cur_mode {
|
||||
Mode::Libstd => libstd_stamp(builder, compiler, target),
|
||||
Mode::Libtest => libtest_stamp(builder, compiler, target),
|
||||
Mode::Librustc => librustc_stamp(builder, compiler, target),
|
||||
Mode::Std => libstd_stamp(builder, compiler, target),
|
||||
Mode::Test => libtest_stamp(builder, compiler, target),
|
||||
Mode::Rustc => librustc_stamp(builder, compiler, target),
|
||||
_ => panic!(),
|
||||
};
|
||||
|
||||
@ -67,7 +67,7 @@ impl Step for CleanTools {
|
||||
|
||||
// If we are a rustc tool, and std changed, we also need to clear ourselves out -- our
|
||||
// dependencies depend on std. Therefore, we iterate up until our own mode.
|
||||
if mode == cur_mode {
|
||||
if cause == cur_mode {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -104,13 +104,13 @@ impl Step for ToolBuild {
|
||||
let is_ext_tool = self.is_ext_tool;
|
||||
|
||||
match self.mode {
|
||||
Mode::Libstd => builder.ensure(compile::Std { compiler, target }),
|
||||
Mode::Libtest => builder.ensure(compile::Test { compiler, target }),
|
||||
Mode::Librustc => builder.ensure(compile::Rustc { compiler, target }),
|
||||
Mode::Tool => panic!("unexpected Mode::Tool for tool build")
|
||||
Mode::ToolStd => builder.ensure(compile::Std { compiler, target }),
|
||||
Mode::ToolTest => builder.ensure(compile::Test { compiler, target }),
|
||||
Mode::ToolRustc => builder.ensure(compile::Rustc { compiler, target }),
|
||||
_ => panic!("unexpected Mode for tool build")
|
||||
}
|
||||
|
||||
let mut cargo = prepare_tool_cargo(builder, compiler, target, "build", path);
|
||||
let mut cargo = prepare_tool_cargo(builder, compiler, self.mode, target, "build", path);
|
||||
cargo.arg("--features").arg(self.extra_features.join(" "));
|
||||
|
||||
let _folder = builder.fold_output(|| format!("stage{}-{}", compiler.stage, tool));
|
||||
@ -202,7 +202,7 @@ impl Step for ToolBuild {
|
||||
return None;
|
||||
}
|
||||
} else {
|
||||
let cargo_out = builder.cargo_out(compiler, Mode::Tool, target)
|
||||
let cargo_out = builder.cargo_out(compiler, self.mode, target)
|
||||
.join(exe(tool, &compiler.host));
|
||||
let bin = builder.tools_dir(compiler).join(exe(tool, &compiler.host));
|
||||
builder.copy(&cargo_out, &bin);
|
||||
@ -214,11 +214,12 @@ impl Step for ToolBuild {
|
||||
pub fn prepare_tool_cargo(
|
||||
builder: &Builder,
|
||||
compiler: Compiler,
|
||||
mode: Mode,
|
||||
target: Interned<String>,
|
||||
command: &'static str,
|
||||
path: &'static str,
|
||||
) -> Command {
|
||||
let mut cargo = builder.cargo(compiler, Mode::Tool, target, command);
|
||||
let mut cargo = builder.cargo(compiler, mode, target, command);
|
||||
let dir = builder.src.join(path);
|
||||
cargo.arg("--manifest-path").arg(dir.join("Cargo.toml"));
|
||||
|
||||
@ -261,6 +262,15 @@ macro_rules! tool {
|
||||
)+
|
||||
}
|
||||
|
||||
impl Tool {
|
||||
pub fn get_mode(&self) -> Mode {
|
||||
let mode = match self {
|
||||
$(Tool::$name => $mode,)+
|
||||
};
|
||||
mode
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Builder<'a> {
|
||||
pub fn tool_exe(&self, tool: Tool) -> PathBuf {
|
||||
let stage = self.tool_default_stage(tool);
|
||||
@ -324,17 +334,17 @@ macro_rules! tool {
|
||||
}
|
||||
|
||||
tool!(
|
||||
Rustbook, "src/tools/rustbook", "rustbook", Mode::Librustc;
|
||||
ErrorIndex, "src/tools/error_index_generator", "error_index_generator", Mode::Librustc;
|
||||
UnstableBookGen, "src/tools/unstable-book-gen", "unstable-book-gen", Mode::Libstd;
|
||||
Tidy, "src/tools/tidy", "tidy", Mode::Libstd;
|
||||
Linkchecker, "src/tools/linkchecker", "linkchecker", Mode::Libstd;
|
||||
CargoTest, "src/tools/cargotest", "cargotest", Mode::Libstd;
|
||||
Compiletest, "src/tools/compiletest", "compiletest", Mode::Libtest;
|
||||
BuildManifest, "src/tools/build-manifest", "build-manifest", Mode::Libstd;
|
||||
RemoteTestClient, "src/tools/remote-test-client", "remote-test-client", Mode::Libstd;
|
||||
RustInstaller, "src/tools/rust-installer", "fabricate", Mode::Libstd;
|
||||
RustdocTheme, "src/tools/rustdoc-themes", "rustdoc-themes", Mode::Libstd;
|
||||
Rustbook, "src/tools/rustbook", "rustbook", Mode::ToolRustc;
|
||||
ErrorIndex, "src/tools/error_index_generator", "error_index_generator", Mode::ToolRustc;
|
||||
UnstableBookGen, "src/tools/unstable-book-gen", "unstable-book-gen", Mode::ToolStd;
|
||||
Tidy, "src/tools/tidy", "tidy", Mode::ToolStd;
|
||||
Linkchecker, "src/tools/linkchecker", "linkchecker", Mode::ToolStd;
|
||||
CargoTest, "src/tools/cargotest", "cargotest", Mode::ToolStd;
|
||||
Compiletest, "src/tools/compiletest", "compiletest", Mode::ToolTest;
|
||||
BuildManifest, "src/tools/build-manifest", "build-manifest", Mode::ToolStd;
|
||||
RemoteTestClient, "src/tools/remote-test-client", "remote-test-client", Mode::ToolStd;
|
||||
RustInstaller, "src/tools/rust-installer", "fabricate", Mode::ToolStd;
|
||||
RustdocTheme, "src/tools/rustdoc-themes", "rustdoc-themes", Mode::ToolStd;
|
||||
);
|
||||
|
||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||
@ -362,7 +372,7 @@ impl Step for RemoteTestServer {
|
||||
compiler: self.compiler,
|
||||
target: self.target,
|
||||
tool: "remote-test-server",
|
||||
mode: Mode::Libstd,
|
||||
mode: Mode::ToolStd,
|
||||
path: "src/tools/remote-test-server",
|
||||
is_ext_tool: false,
|
||||
extra_features: Vec::new(),
|
||||
@ -414,6 +424,7 @@ impl Step for Rustdoc {
|
||||
|
||||
let mut cargo = prepare_tool_cargo(builder,
|
||||
build_compiler,
|
||||
Mode::ToolRustc,
|
||||
target,
|
||||
"build",
|
||||
"src/tools/rustdoc");
|
||||
@ -430,7 +441,7 @@ impl Step for Rustdoc {
|
||||
// Cargo adds a number of paths to the dylib search path on windows, which results in
|
||||
// the wrong rustdoc being executed. To avoid the conflicting rustdocs, we name the "tool"
|
||||
// rustdoc a different name.
|
||||
let tool_rustdoc = builder.cargo_out(build_compiler, Mode::Tool, target)
|
||||
let tool_rustdoc = builder.cargo_out(build_compiler, Mode::ToolRustc, target)
|
||||
.join(exe("rustdoc_tool_binary", &target_compiler.host));
|
||||
|
||||
// don't create a stage0-sysroot/bin directory.
|
||||
@ -485,7 +496,7 @@ impl Step for Cargo {
|
||||
compiler: self.compiler,
|
||||
target: self.target,
|
||||
tool: "cargo",
|
||||
mode: Mode::Librustc,
|
||||
mode: Mode::ToolRustc,
|
||||
path: "src/tools/cargo",
|
||||
is_ext_tool: false,
|
||||
extra_features: Vec::new(),
|
||||
@ -533,7 +544,7 @@ macro_rules! tool_extended {
|
||||
compiler: $sel.compiler,
|
||||
target: $sel.target,
|
||||
tool: $tool_name,
|
||||
mode: Mode::Librustc,
|
||||
mode: Mode::ToolRustc,
|
||||
path: $path,
|
||||
extra_features: $sel.extra_features,
|
||||
is_ext_tool: true,
|
||||
@ -575,7 +586,7 @@ impl<'a> Builder<'a> {
|
||||
pub fn tool_cmd(&self, tool: Tool) -> Command {
|
||||
let mut cmd = Command::new(self.tool_exe(tool));
|
||||
let compiler = self.compiler(self.tool_default_stage(tool), self.config.build);
|
||||
self.prepare_tool_cmd(compiler, &mut cmd);
|
||||
self.prepare_tool_cmd(compiler, tool.get_mode(), &mut cmd);
|
||||
cmd
|
||||
}
|
||||
|
||||
@ -583,11 +594,11 @@ impl<'a> Builder<'a> {
|
||||
///
|
||||
/// Notably this munges the dynamic library lookup path to point to the
|
||||
/// right location to run `compiler`.
|
||||
fn prepare_tool_cmd(&self, compiler: Compiler, cmd: &mut Command) {
|
||||
fn prepare_tool_cmd(&self, compiler: Compiler, mode: Mode, cmd: &mut Command) {
|
||||
let host = &compiler.host;
|
||||
let mut lib_paths: Vec<PathBuf> = vec![
|
||||
PathBuf::from(&self.sysroot_libdir(compiler, compiler.host)),
|
||||
self.cargo_out(compiler, Mode::Tool, *host).join("deps"),
|
||||
self.cargo_out(compiler, mode, *host).join("deps"),
|
||||
];
|
||||
|
||||
// On MSVC a tool may invoke a C compiler (e.g. compiletest in run-make
|
||||
|
@ -19,6 +19,7 @@ sugar for dynamic allocations via `malloc` and `free`:
|
||||
#![feature(lang_items, box_syntax, start, libc, core_intrinsics)]
|
||||
#![no_std]
|
||||
use core::intrinsics;
|
||||
use core::panic::PanicInfo;
|
||||
|
||||
extern crate libc;
|
||||
|
||||
@ -50,7 +51,7 @@ fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
||||
}
|
||||
|
||||
#[lang = "eh_personality"] extern fn rust_eh_personality() {}
|
||||
#[lang = "panic_fmt"] extern fn rust_begin_panic() -> ! { unsafe { intrinsics::abort() } }
|
||||
#[lang = "panic_impl"] extern fn rust_begin_panic(info: &PanicInfo) -> ! { unsafe { intrinsics::abort() } }
|
||||
#[lang = "eh_unwind_resume"] extern fn rust_eh_unwind_resume() {}
|
||||
#[no_mangle] pub extern fn rust_eh_register_frames () {}
|
||||
#[no_mangle] pub extern fn rust_eh_unregister_frames () {}
|
||||
@ -110,6 +111,7 @@ in the same format as C:
|
||||
#![feature(start)]
|
||||
#![no_std]
|
||||
use core::intrinsics;
|
||||
use core::panic::PanicInfo;
|
||||
|
||||
// Pull in the system libc library for what crt0.o likely requires.
|
||||
extern crate libc;
|
||||
@ -134,12 +136,9 @@ pub extern fn rust_eh_personality() {
|
||||
pub extern fn rust_eh_unwind_resume() {
|
||||
}
|
||||
|
||||
#[lang = "panic_fmt"]
|
||||
#[lang = "panic_impl"]
|
||||
#[no_mangle]
|
||||
pub extern fn rust_begin_panic(_msg: core::fmt::Arguments,
|
||||
_file: &'static str,
|
||||
_line: u32,
|
||||
_column: u32) -> ! {
|
||||
pub extern fn rust_begin_panic(info: &PanicInfo) -> ! {
|
||||
unsafe { intrinsics::abort() }
|
||||
}
|
||||
```
|
||||
@ -155,6 +154,7 @@ compiler's name mangling too:
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
use core::intrinsics;
|
||||
use core::panic::PanicInfo;
|
||||
|
||||
// Pull in the system libc library for what crt0.o likely requires.
|
||||
extern crate libc;
|
||||
@ -179,12 +179,9 @@ pub extern fn rust_eh_personality() {
|
||||
pub extern fn rust_eh_unwind_resume() {
|
||||
}
|
||||
|
||||
#[lang = "panic_fmt"]
|
||||
#[lang = "panic_impl"]
|
||||
#[no_mangle]
|
||||
pub extern fn rust_begin_panic(_msg: core::fmt::Arguments,
|
||||
_file: &'static str,
|
||||
_line: u32,
|
||||
_column: u32) -> ! {
|
||||
pub extern fn rust_begin_panic(info: &PanicInfo) -> ! {
|
||||
unsafe { intrinsics::abort() }
|
||||
}
|
||||
```
|
||||
@ -215,7 +212,7 @@ called. The language item's name is `eh_personality`.
|
||||
|
||||
The second function, `rust_begin_panic`, is also used by the failure mechanisms of the
|
||||
compiler. When a panic happens, this controls the message that's displayed on
|
||||
the screen. While the language item's name is `panic_fmt`, the symbol name is
|
||||
the screen. While the language item's name is `panic_impl`, the symbol name is
|
||||
`rust_begin_panic`.
|
||||
|
||||
A third function, `rust_eh_unwind_resume`, is also needed if the `custom_unwind_resume`
|
||||
@ -259,8 +256,8 @@ the source code.
|
||||
- `msvc_try_filter`: `libpanic_unwind/seh.rs` (SEH)
|
||||
- `panic`: `libcore/panicking.rs`
|
||||
- `panic_bounds_check`: `libcore/panicking.rs`
|
||||
- `panic_fmt`: `libcore/panicking.rs`
|
||||
- `panic_fmt`: `libstd/panicking.rs`
|
||||
- `panic_impl`: `libcore/panicking.rs`
|
||||
- `panic_impl`: `libstd/panicking.rs`
|
||||
- Allocations
|
||||
- `owned_box`: `liballoc/boxed.rs`
|
||||
- `exchange_malloc`: `liballoc/heap.rs`
|
||||
|
@ -87,11 +87,13 @@ This condition can be met using `#[used]` and `#[link_section]` plus a linker
|
||||
script.
|
||||
|
||||
``` rust,ignore
|
||||
#![feature(lang_items)]
|
||||
#![feature(panic_implementation)]
|
||||
#![feature(used)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
use core::panic::PanicInfo;
|
||||
|
||||
extern "C" fn reset_handler() -> ! {
|
||||
loop {}
|
||||
}
|
||||
@ -100,8 +102,10 @@ extern "C" fn reset_handler() -> ! {
|
||||
#[used]
|
||||
static RESET_HANDLER: extern "C" fn() -> ! = reset_handler;
|
||||
|
||||
#[lang = "panic_fmt"]
|
||||
fn panic_fmt() {}
|
||||
#[panic_implementation]
|
||||
fn panic_impl(info: &PanicInfo) -> ! {
|
||||
loop {}
|
||||
}
|
||||
```
|
||||
|
||||
``` text
|
||||
|
@ -2369,6 +2369,11 @@ impl<'a, K: Ord, V> OccupiedEntry<'a, K, V> {
|
||||
|
||||
/// Gets a mutable reference to the value in the entry.
|
||||
///
|
||||
/// If you need a reference to the `OccupiedEntry` which may outlive the
|
||||
/// destruction of the `Entry` value, see [`into_mut`].
|
||||
///
|
||||
/// [`into_mut`]: #method.into_mut
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
@ -2380,9 +2385,13 @@ impl<'a, K: Ord, V> OccupiedEntry<'a, K, V> {
|
||||
///
|
||||
/// assert_eq!(map["poneyland"], 12);
|
||||
/// if let Entry::Occupied(mut o) = map.entry("poneyland") {
|
||||
/// *o.get_mut() += 10;
|
||||
/// *o.get_mut() += 10;
|
||||
/// assert_eq!(*o.get(), 22);
|
||||
///
|
||||
/// // We can use the same Entry multiple times.
|
||||
/// *o.get_mut() += 2;
|
||||
/// }
|
||||
/// assert_eq!(map["poneyland"], 22);
|
||||
/// assert_eq!(map["poneyland"], 24);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn get_mut(&mut self) -> &mut V {
|
||||
@ -2391,6 +2400,10 @@ impl<'a, K: Ord, V> OccupiedEntry<'a, K, V> {
|
||||
|
||||
/// Converts the entry into a mutable reference to its value.
|
||||
///
|
||||
/// If you need multiple references to the `OccupiedEntry`, see [`get_mut`].
|
||||
///
|
||||
/// [`get_mut`]: #method.get_mut
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
|
@ -104,7 +104,6 @@
|
||||
#![feature(ptr_internals)]
|
||||
#![feature(ptr_offset_from)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(slice_get_slice)]
|
||||
#![feature(specialization)]
|
||||
#![feature(staged_api)]
|
||||
#![feature(str_internals)]
|
||||
|
@ -121,7 +121,7 @@ pub use core::slice::{RSplit, RSplitMut};
|
||||
pub use core::slice::{from_raw_parts, from_raw_parts_mut};
|
||||
#[stable(feature = "from_ref", since = "1.28.0")]
|
||||
pub use core::slice::{from_ref, from_mut};
|
||||
#[unstable(feature = "slice_get_slice", issue = "35729")]
|
||||
#[stable(feature = "slice_get_slice", since = "1.28.0")]
|
||||
pub use core::slice::SliceIndex;
|
||||
#[unstable(feature = "exact_chunks", issue = "47115")]
|
||||
pub use core::slice::{ExactChunks, ExactChunksMut};
|
||||
|
@ -1326,6 +1326,7 @@ fn test_str_default() {
|
||||
|
||||
t::<&str>();
|
||||
t::<String>();
|
||||
t::<&mut str>();
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -20,6 +20,7 @@ use fmt;
|
||||
use mem;
|
||||
use usize;
|
||||
use ptr::{self, NonNull};
|
||||
use num::NonZeroUsize;
|
||||
|
||||
extern {
|
||||
/// An opaque, unsized type. Used for pointers to allocated memory.
|
||||
@ -66,7 +67,7 @@ fn size_align<T>() -> (usize, usize) {
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub struct Layout {
|
||||
// size of the requested block of memory, measured in bytes.
|
||||
size: usize,
|
||||
size_: usize,
|
||||
|
||||
// alignment of the requested block of memory, measured in bytes.
|
||||
// we ensure that this is always a power-of-two, because API's
|
||||
@ -75,17 +76,12 @@ pub struct Layout {
|
||||
//
|
||||
// (However, we do not analogously require `align >= sizeof(void*)`,
|
||||
// even though that is *also* a requirement of `posix_memalign`.)
|
||||
align: usize,
|
||||
align_: NonZeroUsize,
|
||||
}
|
||||
|
||||
|
||||
// FIXME: audit default implementations for overflow errors,
|
||||
// (potentially switching to overflowing_add and
|
||||
// overflowing_mul as necessary).
|
||||
|
||||
impl Layout {
|
||||
/// Constructs a `Layout` from a given `size` and `align`,
|
||||
/// or returns `None` if either of the following conditions
|
||||
/// or returns `LayoutErr` if either of the following conditions
|
||||
/// are not met:
|
||||
///
|
||||
/// * `align` must be a power of two,
|
||||
@ -126,23 +122,23 @@ impl Layout {
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This function is unsafe as it does not verify that `align` is
|
||||
/// a power-of-two nor `size` aligned to `align` fits within the
|
||||
/// address space (i.e. the `Layout::from_size_align` preconditions).
|
||||
/// This function is unsafe as it does not verify the preconditions from
|
||||
/// [`Layout::from_size_align`](#method.from_size_align).
|
||||
#[inline]
|
||||
pub unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self {
|
||||
Layout { size: size, align: align }
|
||||
Layout { size_: size, align_: NonZeroUsize::new_unchecked(align) }
|
||||
}
|
||||
|
||||
/// The minimum size in bytes for a memory block of this layout.
|
||||
#[inline]
|
||||
pub fn size(&self) -> usize { self.size }
|
||||
pub fn size(&self) -> usize { self.size_ }
|
||||
|
||||
/// The minimum byte alignment for a memory block of this layout.
|
||||
#[inline]
|
||||
pub fn align(&self) -> usize { self.align }
|
||||
pub fn align(&self) -> usize { self.align_.get() }
|
||||
|
||||
/// Constructs a `Layout` suitable for holding a value of type `T`.
|
||||
#[inline]
|
||||
pub fn new<T>() -> Self {
|
||||
let (size, align) = size_align::<T>();
|
||||
// Note that the align is guaranteed by rustc to be a power of two and
|
||||
@ -158,6 +154,7 @@ impl Layout {
|
||||
/// Produces layout describing a record that could be used to
|
||||
/// allocate backing structure for `T` (which could be a trait
|
||||
/// or other unsized type like a slice).
|
||||
#[inline]
|
||||
pub fn for_value<T: ?Sized>(t: &T) -> Self {
|
||||
let (size, align) = (mem::size_of_val(t), mem::align_of_val(t));
|
||||
// See rationale in `new` for why this us using an unsafe variant below
|
||||
@ -181,18 +178,19 @@ impl Layout {
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the combination of `self.size` and the given `align`
|
||||
/// violates the conditions listed in `from_size_align`.
|
||||
/// Panics if the combination of `self.size()` and the given `align`
|
||||
/// violates the conditions listed in
|
||||
/// [`Layout::from_size_align`](#method.from_size_align).
|
||||
#[inline]
|
||||
pub fn align_to(&self, align: usize) -> Self {
|
||||
Layout::from_size_align(self.size, cmp::max(self.align, align)).unwrap()
|
||||
Layout::from_size_align(self.size(), cmp::max(self.align(), align)).unwrap()
|
||||
}
|
||||
|
||||
/// Returns the amount of padding we must insert after `self`
|
||||
/// to ensure that the following address will satisfy `align`
|
||||
/// (measured in bytes).
|
||||
///
|
||||
/// E.g. if `self.size` is 9, then `self.padding_needed_for(4)`
|
||||
/// E.g. if `self.size()` is 9, then `self.padding_needed_for(4)`
|
||||
/// returns 3, because that is the minimum number of bytes of
|
||||
/// padding required to get a 4-aligned address (assuming that the
|
||||
/// corresponding memory block starts at a 4-aligned address).
|
||||
@ -203,7 +201,7 @@ impl Layout {
|
||||
/// Note that the utility of the returned value requires `align`
|
||||
/// to be less than or equal to the alignment of the starting
|
||||
/// address for the whole allocated block of memory. One way to
|
||||
/// satisfy this constraint is to ensure `align <= self.align`.
|
||||
/// satisfy this constraint is to ensure `align <= self.align()`.
|
||||
#[inline]
|
||||
pub fn padding_needed_for(&self, align: usize) -> usize {
|
||||
let len = self.size();
|
||||
@ -227,7 +225,8 @@ impl Layout {
|
||||
// size and padding overflow in the above manner should cause
|
||||
// the allocator to yield an error anyway.)
|
||||
|
||||
let len_rounded_up = len.wrapping_add(align).wrapping_sub(1) & !align.wrapping_sub(1);
|
||||
let len_rounded_up = len.wrapping_add(align).wrapping_sub(1)
|
||||
& !align.wrapping_sub(1);
|
||||
return len_rounded_up.wrapping_sub(len);
|
||||
}
|
||||
|
||||
@ -238,14 +237,19 @@ impl Layout {
|
||||
/// layout of the array and `offs` is the distance between the start
|
||||
/// of each element in the array.
|
||||
///
|
||||
/// On arithmetic overflow, returns `None`.
|
||||
/// On arithmetic overflow, returns `LayoutErr`.
|
||||
#[inline]
|
||||
pub fn repeat(&self, n: usize) -> Result<(Self, usize), LayoutErr> {
|
||||
let padded_size = self.size.checked_add(self.padding_needed_for(self.align))
|
||||
let padded_size = self.size().checked_add(self.padding_needed_for(self.align()))
|
||||
.ok_or(LayoutErr { private: () })?;
|
||||
let alloc_size = padded_size.checked_mul(n)
|
||||
.ok_or(LayoutErr { private: () })?;
|
||||
Ok((Layout::from_size_align(alloc_size, self.align)?, padded_size))
|
||||
|
||||
unsafe {
|
||||
// self.align is already known to be valid and alloc_size has been
|
||||
// padded already.
|
||||
Ok((Layout::from_size_align_unchecked(alloc_size, self.align()), padded_size))
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a layout describing the record for `self` followed by
|
||||
@ -258,16 +262,15 @@ impl Layout {
|
||||
/// start of the `next` embedded within the concatenated record
|
||||
/// (assuming that the record itself starts at offset 0).
|
||||
///
|
||||
/// On arithmetic overflow, returns `None`.
|
||||
/// On arithmetic overflow, returns `LayoutErr`.
|
||||
#[inline]
|
||||
pub fn extend(&self, next: Self) -> Result<(Self, usize), LayoutErr> {
|
||||
let new_align = cmp::max(self.align, next.align);
|
||||
let realigned = Layout::from_size_align(self.size, new_align)?;
|
||||
let new_align = cmp::max(self.align(), next.align());
|
||||
let pad = self.padding_needed_for(next.align());
|
||||
|
||||
let pad = realigned.padding_needed_for(next.align);
|
||||
|
||||
let offset = self.size.checked_add(pad)
|
||||
let offset = self.size().checked_add(pad)
|
||||
.ok_or(LayoutErr { private: () })?;
|
||||
let new_size = offset.checked_add(next.size)
|
||||
let new_size = offset.checked_add(next.size())
|
||||
.ok_or(LayoutErr { private: () })?;
|
||||
|
||||
let layout = Layout::from_size_align(new_size, new_align)?;
|
||||
@ -285,10 +288,11 @@ impl Layout {
|
||||
/// guaranteed that all elements in the array will be properly
|
||||
/// aligned.
|
||||
///
|
||||
/// On arithmetic overflow, returns `None`.
|
||||
/// On arithmetic overflow, returns `LayoutErr`.
|
||||
#[inline]
|
||||
pub fn repeat_packed(&self, n: usize) -> Result<Self, LayoutErr> {
|
||||
let size = self.size().checked_mul(n).ok_or(LayoutErr { private: () })?;
|
||||
Layout::from_size_align(size, self.align)
|
||||
Layout::from_size_align(size, self.align())
|
||||
}
|
||||
|
||||
/// Creates a layout describing the record for `self` followed by
|
||||
@ -305,17 +309,19 @@ impl Layout {
|
||||
/// signature out of convenience in matching the signature of
|
||||
/// `extend`.)
|
||||
///
|
||||
/// On arithmetic overflow, returns `None`.
|
||||
/// On arithmetic overflow, returns `LayoutErr`.
|
||||
#[inline]
|
||||
pub fn extend_packed(&self, next: Self) -> Result<(Self, usize), LayoutErr> {
|
||||
let new_size = self.size().checked_add(next.size())
|
||||
.ok_or(LayoutErr { private: () })?;
|
||||
let layout = Layout::from_size_align(new_size, self.align)?;
|
||||
let layout = Layout::from_size_align(new_size, self.align())?;
|
||||
Ok((layout, self.size()))
|
||||
}
|
||||
|
||||
/// Creates a layout describing the record for a `[T; n]`.
|
||||
///
|
||||
/// On arithmetic overflow, returns `None`.
|
||||
/// On arithmetic overflow, returns `LayoutErr`.
|
||||
#[inline]
|
||||
pub fn array<T>(n: usize) -> Result<Self, LayoutErr> {
|
||||
Layout::new::<T>()
|
||||
.repeat(n)
|
||||
@ -842,7 +848,7 @@ pub unsafe trait Alloc {
|
||||
layout: Layout,
|
||||
new_size: usize) -> Result<(), CannotReallocInPlace> {
|
||||
let _ = ptr; // this default implementation doesn't care about the actual address.
|
||||
debug_assert!(new_size >= layout.size);
|
||||
debug_assert!(new_size >= layout.size());
|
||||
let (_l, u) = self.usable_size(&layout);
|
||||
// _l <= layout.size() [guaranteed by usable_size()]
|
||||
// layout.size() <= new_layout.size() [required by this method]
|
||||
@ -897,7 +903,7 @@ pub unsafe trait Alloc {
|
||||
layout: Layout,
|
||||
new_size: usize) -> Result<(), CannotReallocInPlace> {
|
||||
let _ = ptr; // this default implementation doesn't care about the actual address.
|
||||
debug_assert!(new_size <= layout.size);
|
||||
debug_assert!(new_size <= layout.size());
|
||||
let (l, _u) = self.usable_size(&layout);
|
||||
// layout.size() <= _u [guaranteed by usable_size()]
|
||||
// new_layout.size() <= layout.size() [required by this method]
|
||||
|
@ -41,7 +41,7 @@
|
||||
//! dictate the panic message, the file at which panic was invoked, and the
|
||||
//! line and column inside the file. It is up to consumers of this core
|
||||
//! library to define this panic function; it is only required to never
|
||||
//! return. This requires a `lang` attribute named `panic_fmt`.
|
||||
//! return. This requires a `lang` attribute named `panic_impl`.
|
||||
//!
|
||||
//! * `rust_eh_personality` - is used by the failure mechanisms of the
|
||||
//! compiler. This is often mapped to GCC's personality function, but crates
|
||||
@ -81,6 +81,7 @@
|
||||
#![feature(cfg_target_has_atomic)]
|
||||
#![feature(concat_idents)]
|
||||
#![feature(const_fn)]
|
||||
#![feature(const_int_ops)]
|
||||
#![feature(core_float)]
|
||||
#![feature(custom_attribute)]
|
||||
#![feature(doc_cfg)]
|
||||
|
@ -635,8 +635,9 @@ 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 either one.
|
||||
/// Moves `src` into the referenced `dest`, returning the previous `dest` value.
|
||||
///
|
||||
/// Neither value is dropped.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -31,7 +31,11 @@ pub const MANTISSA_DIGITS: u32 = 24;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const DIGITS: u32 = 6;
|
||||
|
||||
/// Difference between `1.0` and the next largest representable number.
|
||||
/// [Machine epsilon] value for `f32`.
|
||||
///
|
||||
/// This is the difference between `1.0` and the next largest representable number.
|
||||
///
|
||||
/// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const EPSILON: f32 = 1.19209290e-07_f32;
|
||||
|
||||
|
@ -31,7 +31,11 @@ pub const MANTISSA_DIGITS: u32 = 53;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const DIGITS: u32 = 15;
|
||||
|
||||
/// Difference between `1.0` and the next largest representable number.
|
||||
/// [Machine epsilon] value for `f64`.
|
||||
///
|
||||
/// This is the difference between `1.0` and the next largest representable number.
|
||||
///
|
||||
/// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const EPSILON: f64 = 2.2204460492503131e-16_f64;
|
||||
|
||||
|
@ -267,6 +267,16 @@ $EndFeature, "
|
||||
```
|
||||
"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg(not(stage0))]
|
||||
#[rustc_const_unstable(feature = "const_int_ops")]
|
||||
#[inline]
|
||||
pub const fn count_ones(self) -> u32 { (self as $UnsignedT).count_ones() }
|
||||
}
|
||||
|
||||
doc_comment! {
|
||||
concat!("Dummy docs. See !stage0 documentation"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg(stage0)]
|
||||
#[inline]
|
||||
pub fn count_ones(self) -> u32 { (self as $UnsignedT).count_ones() }
|
||||
}
|
||||
@ -282,6 +292,18 @@ Basic usage:
|
||||
", $Feature, "assert_eq!(", stringify!($SelfT), "::max_value().count_zeros(), 1);", $EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg(not(stage0))]
|
||||
#[rustc_const_unstable(feature = "const_int_ops")]
|
||||
#[inline]
|
||||
pub const fn count_zeros(self) -> u32 {
|
||||
(!self).count_ones()
|
||||
}
|
||||
}
|
||||
|
||||
doc_comment! {
|
||||
concat!("Dummy docs. See !stage0 documentatio"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg(stage0)]
|
||||
#[inline]
|
||||
pub fn count_zeros(self) -> u32 {
|
||||
(!self).count_ones()
|
||||
@ -302,6 +324,18 @@ assert_eq!(n.leading_zeros(), 0);",
|
||||
$EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg(not(stage0))]
|
||||
#[rustc_const_unstable(feature = "const_int_ops")]
|
||||
#[inline]
|
||||
pub const fn leading_zeros(self) -> u32 {
|
||||
(self as $UnsignedT).leading_zeros()
|
||||
}
|
||||
}
|
||||
|
||||
doc_comment! {
|
||||
concat!("Dummy docs. See !stage0 documentation"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg(stage0)]
|
||||
#[inline]
|
||||
pub fn leading_zeros(self) -> u32 {
|
||||
(self as $UnsignedT).leading_zeros()
|
||||
@ -322,6 +356,18 @@ assert_eq!(n.trailing_zeros(), 2);",
|
||||
$EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg(not(stage0))]
|
||||
#[rustc_const_unstable(feature = "const_int_ops")]
|
||||
#[inline]
|
||||
pub const fn trailing_zeros(self) -> u32 {
|
||||
(self as $UnsignedT).trailing_zeros()
|
||||
}
|
||||
}
|
||||
|
||||
doc_comment! {
|
||||
concat!("Dummy docs. See !stage0 documentation"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg(stage0)]
|
||||
#[inline]
|
||||
pub fn trailing_zeros(self) -> u32 {
|
||||
(self as $UnsignedT).trailing_zeros()
|
||||
@ -396,6 +442,16 @@ $EndFeature, "
|
||||
/// assert_eq!(m, 21760);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg(not(stage0))]
|
||||
#[rustc_const_unstable(feature = "const_int_ops")]
|
||||
#[inline]
|
||||
pub const fn swap_bytes(self) -> Self {
|
||||
(self as $UnsignedT).swap_bytes() as Self
|
||||
}
|
||||
|
||||
/// Dummy docs. See !stage0 documentation.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg(stage0)]
|
||||
#[inline]
|
||||
pub fn swap_bytes(self) -> Self {
|
||||
(self as $UnsignedT).swap_bytes() as Self
|
||||
@ -447,6 +503,25 @@ if cfg!(target_endian = \"big\") {
|
||||
$EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg(not(stage0))]
|
||||
#[rustc_const_unstable(feature = "const_int_ops")]
|
||||
#[inline]
|
||||
pub const fn from_be(x: Self) -> Self {
|
||||
#[cfg(target_endian = "big")]
|
||||
{
|
||||
x
|
||||
}
|
||||
#[cfg(not(target_endian = "big"))]
|
||||
{
|
||||
x.swap_bytes()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
doc_comment! {
|
||||
concat!("Dummy docs. See !stage0 documentation"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg(stage0)]
|
||||
#[inline]
|
||||
pub fn from_be(x: Self) -> Self {
|
||||
if cfg!(target_endian = "big") { x } else { x.swap_bytes() }
|
||||
@ -473,6 +548,25 @@ if cfg!(target_endian = \"little\") {
|
||||
$EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg(not(stage0))]
|
||||
#[rustc_const_unstable(feature = "const_int_ops")]
|
||||
#[inline]
|
||||
pub const fn from_le(x: Self) -> Self {
|
||||
#[cfg(target_endian = "little")]
|
||||
{
|
||||
x
|
||||
}
|
||||
#[cfg(not(target_endian = "little"))]
|
||||
{
|
||||
x.swap_bytes()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
doc_comment! {
|
||||
concat!("Dummy docs. See !stage0 documentation"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg(stage0)]
|
||||
#[inline]
|
||||
pub fn from_le(x: Self) -> Self {
|
||||
if cfg!(target_endian = "little") { x } else { x.swap_bytes() }
|
||||
@ -499,6 +593,25 @@ if cfg!(target_endian = \"big\") {
|
||||
$EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg(not(stage0))]
|
||||
#[rustc_const_unstable(feature = "const_int_ops")]
|
||||
#[inline]
|
||||
pub const fn to_be(self) -> Self { // or not to be?
|
||||
#[cfg(target_endian = "big")]
|
||||
{
|
||||
self
|
||||
}
|
||||
#[cfg(not(target_endian = "big"))]
|
||||
{
|
||||
self.swap_bytes()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
doc_comment! {
|
||||
concat!("Dummy docs. See !stage0 documentation"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg(stage0)]
|
||||
#[inline]
|
||||
pub fn to_be(self) -> Self { // or not to be?
|
||||
if cfg!(target_endian = "big") { self } else { self.swap_bytes() }
|
||||
@ -525,6 +638,25 @@ if cfg!(target_endian = \"little\") {
|
||||
$EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg(not(stage0))]
|
||||
#[rustc_const_unstable(feature = "const_int_ops")]
|
||||
#[inline]
|
||||
pub const fn to_le(self) -> Self {
|
||||
#[cfg(target_endian = "little")]
|
||||
{
|
||||
self
|
||||
}
|
||||
#[cfg(not(target_endian = "little"))]
|
||||
{
|
||||
self.swap_bytes()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
doc_comment! {
|
||||
concat!("Dummy docs. See !stage0 documentation"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg(stage0)]
|
||||
#[inline]
|
||||
pub fn to_le(self) -> Self {
|
||||
if cfg!(target_endian = "little") { self } else { self.swap_bytes() }
|
||||
@ -1943,6 +2075,19 @@ impl isize {
|
||||
int_impl! { isize, i64, u64, 64, -9223372036854775808, 9223372036854775807, "", "" }
|
||||
}
|
||||
|
||||
// Emits the correct `cttz` call, depending on the size of the type.
|
||||
macro_rules! uint_cttz_call {
|
||||
// As of LLVM 3.6 the codegen for the zero-safe cttz8 intrinsic
|
||||
// emits two conditional moves on x86_64. By promoting the value to
|
||||
// u16 and setting bit 8, we get better code without any conditional
|
||||
// operations.
|
||||
// FIXME: There's a LLVM patch (http://reviews.llvm.org/D9284)
|
||||
// pending, remove this workaround once LLVM generates better code
|
||||
// for cttz8.
|
||||
($value:expr, 8) => { intrinsics::cttz($value as u16 | 0x100) };
|
||||
($value:expr, $_BITS:expr) => { intrinsics::cttz($value) }
|
||||
}
|
||||
|
||||
// `Int` + `UnsignedInt` implemented for unsigned integers
|
||||
macro_rules! uint_impl {
|
||||
($SelfT:ty, $ActualT:ty, $BITS:expr, $MaxV:expr, $Feature:expr, $EndFeature:expr) => {
|
||||
@ -2020,6 +2165,18 @@ Basic usage:
|
||||
assert_eq!(n.count_ones(), 3);", $EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg(not(stage0))]
|
||||
#[rustc_const_unstable(feature = "const_int_ops")]
|
||||
#[inline]
|
||||
pub const fn count_ones(self) -> u32 {
|
||||
unsafe { intrinsics::ctpop(self as $ActualT) as u32 }
|
||||
}
|
||||
}
|
||||
|
||||
doc_comment! {
|
||||
concat!("Dummy docs. See !stage0 documentation"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg(stage0)]
|
||||
#[inline]
|
||||
pub fn count_ones(self) -> u32 {
|
||||
unsafe { intrinsics::ctpop(self as $ActualT) as u32 }
|
||||
@ -2037,6 +2194,18 @@ Basic usage:
|
||||
", $Feature, "assert_eq!(", stringify!($SelfT), "::max_value().count_zeros(), 0);", $EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg(not(stage0))]
|
||||
#[rustc_const_unstable(feature = "const_int_ops")]
|
||||
#[inline]
|
||||
pub const fn count_zeros(self) -> u32 {
|
||||
(!self).count_ones()
|
||||
}
|
||||
}
|
||||
|
||||
doc_comment! {
|
||||
concat!("Dummy docs. See !stage0 documentation"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg(stage0)]
|
||||
#[inline]
|
||||
pub fn count_zeros(self) -> u32 {
|
||||
(!self).count_ones()
|
||||
@ -2056,6 +2225,18 @@ Basic usage:
|
||||
assert_eq!(n.leading_zeros(), 2);", $EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg(not(stage0))]
|
||||
#[rustc_const_unstable(feature = "const_int_ops")]
|
||||
#[inline]
|
||||
pub const fn leading_zeros(self) -> u32 {
|
||||
unsafe { intrinsics::ctlz(self as $ActualT) as u32 }
|
||||
}
|
||||
}
|
||||
|
||||
doc_comment! {
|
||||
concat!("Dummy docs. See !stage0 documentation"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg(stage0)]
|
||||
#[inline]
|
||||
pub fn leading_zeros(self) -> u32 {
|
||||
unsafe { intrinsics::ctlz(self as $ActualT) as u32 }
|
||||
@ -2076,22 +2257,21 @@ Basic usage:
|
||||
assert_eq!(n.trailing_zeros(), 3);", $EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg(not(stage0))]
|
||||
#[rustc_const_unstable(feature = "const_int_ops")]
|
||||
#[inline]
|
||||
pub const fn trailing_zeros(self) -> u32 {
|
||||
unsafe { uint_cttz_call!(self, $BITS) as u32 }
|
||||
}
|
||||
}
|
||||
|
||||
doc_comment! {
|
||||
concat!("Dummy docs. See !stage0 documentation"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg(stage0)]
|
||||
#[inline]
|
||||
pub fn trailing_zeros(self) -> u32 {
|
||||
// As of LLVM 3.6 the codegen for the zero-safe cttz8 intrinsic
|
||||
// emits two conditional moves on x86_64. By promoting the value to
|
||||
// u16 and setting bit 8, we get better code without any conditional
|
||||
// operations.
|
||||
// FIXME: There's a LLVM patch (http://reviews.llvm.org/D9284)
|
||||
// pending, remove this workaround once LLVM generates better code
|
||||
// for cttz8.
|
||||
unsafe {
|
||||
if $BITS == 8 {
|
||||
intrinsics::cttz(self as u16 | 0x100) as u32
|
||||
} else {
|
||||
intrinsics::cttz(self) as u32
|
||||
}
|
||||
}
|
||||
unsafe { uint_cttz_call!(self, $BITS) as u32 }
|
||||
}
|
||||
}
|
||||
|
||||
@ -2167,6 +2347,16 @@ assert_eq!(n.trailing_zeros(), 3);", $EndFeature, "
|
||||
/// assert_eq!(m, 21760);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg(not(stage0))]
|
||||
#[rustc_const_unstable(feature = "const_int_ops")]
|
||||
#[inline]
|
||||
pub const fn swap_bytes(self) -> Self {
|
||||
unsafe { intrinsics::bswap(self as $ActualT) as Self }
|
||||
}
|
||||
|
||||
/// Dummy docs. See !stage0 documentation.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg(stage0)]
|
||||
#[inline]
|
||||
pub fn swap_bytes(self) -> Self {
|
||||
unsafe { intrinsics::bswap(self as $ActualT) as Self }
|
||||
@ -2218,6 +2408,25 @@ if cfg!(target_endian = \"big\") {
|
||||
}", $EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg(not(stage0))]
|
||||
#[rustc_const_unstable(feature = "const_int_ops")]
|
||||
#[inline]
|
||||
pub const fn from_be(x: Self) -> Self {
|
||||
#[cfg(target_endian = "big")]
|
||||
{
|
||||
x
|
||||
}
|
||||
#[cfg(not(target_endian = "big"))]
|
||||
{
|
||||
x.swap_bytes()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
doc_comment! {
|
||||
concat!("Dummy docs. See !stage0 documentation"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg(stage0)]
|
||||
#[inline]
|
||||
pub fn from_be(x: Self) -> Self {
|
||||
if cfg!(target_endian = "big") { x } else { x.swap_bytes() }
|
||||
@ -2244,6 +2453,25 @@ if cfg!(target_endian = \"little\") {
|
||||
}", $EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg(not(stage0))]
|
||||
#[rustc_const_unstable(feature = "const_int_ops")]
|
||||
#[inline]
|
||||
pub const fn from_le(x: Self) -> Self {
|
||||
#[cfg(target_endian = "little")]
|
||||
{
|
||||
x
|
||||
}
|
||||
#[cfg(not(target_endian = "little"))]
|
||||
{
|
||||
x.swap_bytes()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
doc_comment! {
|
||||
concat!("Dummy docs. See !stage0 documentation"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg(stage0)]
|
||||
#[inline]
|
||||
pub fn from_le(x: Self) -> Self {
|
||||
if cfg!(target_endian = "little") { x } else { x.swap_bytes() }
|
||||
@ -2270,6 +2498,25 @@ if cfg!(target_endian = \"big\") {
|
||||
}", $EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg(not(stage0))]
|
||||
#[rustc_const_unstable(feature = "const_int_ops")]
|
||||
#[inline]
|
||||
pub const fn to_be(self) -> Self { // or not to be?
|
||||
#[cfg(target_endian = "big")]
|
||||
{
|
||||
self
|
||||
}
|
||||
#[cfg(not(target_endian = "big"))]
|
||||
{
|
||||
self.swap_bytes()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
doc_comment! {
|
||||
concat!("Dummy docs. See !stage0 documentation"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg(stage0)]
|
||||
#[inline]
|
||||
pub fn to_be(self) -> Self { // or not to be?
|
||||
if cfg!(target_endian = "big") { self } else { self.swap_bytes() }
|
||||
@ -2296,6 +2543,25 @@ if cfg!(target_endian = \"little\") {
|
||||
}", $EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg(not(stage0))]
|
||||
#[rustc_const_unstable(feature = "const_int_ops")]
|
||||
#[inline]
|
||||
pub const fn to_le(self) -> Self {
|
||||
#[cfg(target_endian = "little")]
|
||||
{
|
||||
self
|
||||
}
|
||||
#[cfg(not(target_endian = "little"))]
|
||||
{
|
||||
self.swap_bytes()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
doc_comment! {
|
||||
concat!("Dummy docs. See !stage0 documentation"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg(stage0)]
|
||||
#[inline]
|
||||
pub fn to_le(self) -> Self {
|
||||
if cfg!(target_endian = "little") { self } else { self.swap_bytes() }
|
||||
|
@ -35,6 +35,7 @@ use fmt;
|
||||
///
|
||||
/// panic!("Normal panic");
|
||||
/// ```
|
||||
#[cfg_attr(not(stage0), lang = "panic_info")]
|
||||
#[stable(feature = "panic_hooks", since = "1.10.0")]
|
||||
#[derive(Debug)]
|
||||
pub struct PanicInfo<'a> {
|
||||
@ -53,7 +54,8 @@ impl<'a> PanicInfo<'a> {
|
||||
pub fn internal_constructor(message: Option<&'a fmt::Arguments<'a>>,
|
||||
location: Location<'a>)
|
||||
-> Self {
|
||||
PanicInfo { payload: &(), location, message }
|
||||
struct NoPayload;
|
||||
PanicInfo { payload: &NoPayload, location, message }
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
@ -121,7 +123,7 @@ impl<'a> PanicInfo<'a> {
|
||||
#[stable(feature = "panic_hooks", since = "1.10.0")]
|
||||
pub fn location(&self) -> Option<&Location> {
|
||||
// NOTE: If this is changed to sometimes return None,
|
||||
// deal with that case in std::panicking::default_hook.
|
||||
// deal with that case in std::panicking::default_hook and std::panicking::begin_panic_fmt.
|
||||
Some(&self.location)
|
||||
}
|
||||
}
|
||||
|
@ -37,6 +37,8 @@
|
||||
issue = "0")]
|
||||
|
||||
use fmt;
|
||||
#[cfg(not(stage0))]
|
||||
use panic::{Location, PanicInfo};
|
||||
|
||||
#[cold] #[inline(never)] // this is the slow path, always
|
||||
#[lang = "panic"]
|
||||
@ -59,6 +61,7 @@ fn panic_bounds_check(file_line_col: &(&'static str, u32, u32),
|
||||
len, index), file_line_col)
|
||||
}
|
||||
|
||||
#[cfg(stage0)]
|
||||
#[cold] #[inline(never)]
|
||||
pub fn panic_fmt(fmt: fmt::Arguments, file_line_col: &(&'static str, u32, u32)) -> ! {
|
||||
#[allow(improper_ctypes)]
|
||||
@ -70,3 +73,21 @@ pub fn panic_fmt(fmt: fmt::Arguments, file_line_col: &(&'static str, u32, u32))
|
||||
let (file, line, col) = *file_line_col;
|
||||
unsafe { panic_impl(fmt, file, line, col) }
|
||||
}
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
#[cold] #[inline(never)]
|
||||
pub fn panic_fmt(fmt: fmt::Arguments, file_line_col: &(&'static str, u32, u32)) -> ! {
|
||||
// NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call
|
||||
#[allow(improper_ctypes)] // PanicInfo contains a trait object which is not FFI safe
|
||||
extern "Rust" {
|
||||
#[lang = "panic_impl"]
|
||||
fn panic_impl(pi: &PanicInfo) -> !;
|
||||
}
|
||||
|
||||
let (file, line, col) = *file_line_col;
|
||||
let pi = PanicInfo::internal_constructor(
|
||||
Some(&fmt),
|
||||
Location::internal_constructor(file, line, col),
|
||||
);
|
||||
unsafe { panic_impl(&pi) }
|
||||
}
|
||||
|
@ -239,8 +239,9 @@ unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) {
|
||||
}
|
||||
}
|
||||
|
||||
/// Replaces the value at `dest` with `src`, returning the old
|
||||
/// value, without dropping either.
|
||||
/// Moves `src` into the pointed `dest`, returning the previous `dest` value.
|
||||
///
|
||||
/// Neither value is dropped.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
|
@ -1977,35 +1977,63 @@ fn slice_index_overflow_fail() -> ! {
|
||||
panic!("attempted to index slice up to maximum usize");
|
||||
}
|
||||
|
||||
mod private_slice_index {
|
||||
use super::ops;
|
||||
#[stable(feature = "slice_get_slice", since = "1.28.0")]
|
||||
pub trait Sealed {}
|
||||
|
||||
#[stable(feature = "slice_get_slice", since = "1.28.0")]
|
||||
impl Sealed for usize {}
|
||||
#[stable(feature = "slice_get_slice", since = "1.28.0")]
|
||||
impl Sealed for ops::Range<usize> {}
|
||||
#[stable(feature = "slice_get_slice", since = "1.28.0")]
|
||||
impl Sealed for ops::RangeTo<usize> {}
|
||||
#[stable(feature = "slice_get_slice", since = "1.28.0")]
|
||||
impl Sealed for ops::RangeFrom<usize> {}
|
||||
#[stable(feature = "slice_get_slice", since = "1.28.0")]
|
||||
impl Sealed for ops::RangeFull {}
|
||||
#[stable(feature = "slice_get_slice", since = "1.28.0")]
|
||||
impl Sealed for ops::RangeInclusive<usize> {}
|
||||
#[stable(feature = "slice_get_slice", since = "1.28.0")]
|
||||
impl Sealed for ops::RangeToInclusive<usize> {}
|
||||
}
|
||||
|
||||
/// A helper trait used for indexing operations.
|
||||
#[unstable(feature = "slice_get_slice", issue = "35729")]
|
||||
#[stable(feature = "slice_get_slice", since = "1.28.0")]
|
||||
#[rustc_on_unimplemented = "slice indices are of type `usize` or ranges of `usize`"]
|
||||
pub trait SliceIndex<T: ?Sized> {
|
||||
pub trait SliceIndex<T: ?Sized>: private_slice_index::Sealed {
|
||||
/// The output type returned by methods.
|
||||
#[stable(feature = "slice_get_slice", since = "1.28.0")]
|
||||
type Output: ?Sized;
|
||||
|
||||
/// Returns a shared reference to the output at this location, if in
|
||||
/// bounds.
|
||||
#[unstable(feature = "slice_index_methods", issue = "0")]
|
||||
fn get(self, slice: &T) -> Option<&Self::Output>;
|
||||
|
||||
/// Returns a mutable reference to the output at this location, if in
|
||||
/// bounds.
|
||||
#[unstable(feature = "slice_index_methods", issue = "0")]
|
||||
fn get_mut(self, slice: &mut T) -> Option<&mut Self::Output>;
|
||||
|
||||
/// Returns a shared reference to the output at this location, without
|
||||
/// performing any bounds checking.
|
||||
#[unstable(feature = "slice_index_methods", issue = "0")]
|
||||
unsafe fn get_unchecked(self, slice: &T) -> &Self::Output;
|
||||
|
||||
/// Returns a mutable reference to the output at this location, without
|
||||
/// performing any bounds checking.
|
||||
#[unstable(feature = "slice_index_methods", issue = "0")]
|
||||
unsafe fn get_unchecked_mut(self, slice: &mut T) -> &mut Self::Output;
|
||||
|
||||
/// Returns a shared reference to the output at this location, panicking
|
||||
/// if out of bounds.
|
||||
#[unstable(feature = "slice_index_methods", issue = "0")]
|
||||
fn index(self, slice: &T) -> &Self::Output;
|
||||
|
||||
/// Returns a mutable reference to the output at this location, panicking
|
||||
/// if out of bounds.
|
||||
#[unstable(feature = "slice_index_methods", issue = "0")]
|
||||
fn index_mut(self, slice: &mut T) -> &mut Self::Output;
|
||||
}
|
||||
|
||||
@ -2513,6 +2541,12 @@ macro_rules! iterator {
|
||||
accum
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<'a, T> FusedIterator for $name<'a, T> {}
|
||||
|
||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
unsafe impl<'a, T> TrustedLen for $name<'a, T> {}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2639,12 +2673,6 @@ impl<'a, T> ExactSizeIterator for Iter<'a, T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<'a, T> FusedIterator for Iter<'a, T> {}
|
||||
|
||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
unsafe impl<'a, T> TrustedLen for Iter<'a, T> {}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a, T> Clone for Iter<'a, T> {
|
||||
fn clone(&self) -> Iter<'a, T> { Iter { ptr: self.ptr, end: self.end, _marker: self._marker } }
|
||||
@ -2706,9 +2734,7 @@ impl<'a, T> IterMut<'a, T> {
|
||||
/// View the underlying data as a subslice of the original data.
|
||||
///
|
||||
/// To avoid creating `&mut` references that alias, this is forced
|
||||
/// to consume the iterator. Consider using the `Slice` and
|
||||
/// `SliceMut` implementations for obtaining slices with more
|
||||
/// restricted lifetimes that do not consume the iterator.
|
||||
/// to consume the iterator.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -2767,13 +2793,6 @@ impl<'a, T> ExactSizeIterator for IterMut<'a, T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<'a, T> FusedIterator for IterMut<'a, T> {}
|
||||
|
||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
unsafe impl<'a, T> TrustedLen for IterMut<'a, T> {}
|
||||
|
||||
|
||||
// Return the number of elements of `T` from `start` to `end`.
|
||||
// Return the arithmetic difference if `T` is zero size.
|
||||
#[inline(always)]
|
||||
@ -3371,6 +3390,9 @@ impl<'a, T> DoubleEndedIterator for Windows<'a, T> {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a, T> ExactSizeIterator for Windows<'a, T> {}
|
||||
|
||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
unsafe impl<'a, T> TrustedLen for Windows<'a, T> {}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<'a, T> FusedIterator for Windows<'a, T> {}
|
||||
|
||||
@ -3490,6 +3512,9 @@ impl<'a, T> DoubleEndedIterator for Chunks<'a, T> {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a, T> ExactSizeIterator for Chunks<'a, T> {}
|
||||
|
||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
unsafe impl<'a, T> TrustedLen for Chunks<'a, T> {}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<'a, T> FusedIterator for Chunks<'a, T> {}
|
||||
|
||||
@ -3606,6 +3631,9 @@ impl<'a, T> DoubleEndedIterator for ChunksMut<'a, T> {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a, T> ExactSizeIterator for ChunksMut<'a, T> {}
|
||||
|
||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
unsafe impl<'a, T> TrustedLen for ChunksMut<'a, T> {}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<'a, T> FusedIterator for ChunksMut<'a, T> {}
|
||||
|
||||
@ -3716,6 +3744,9 @@ impl<'a, T> ExactSizeIterator for ExactChunks<'a, T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
unsafe impl<'a, T> TrustedLen for ExactChunks<'a, T> {}
|
||||
|
||||
#[unstable(feature = "exact_chunks", issue = "47115")]
|
||||
impl<'a, T> FusedIterator for ExactChunks<'a, T> {}
|
||||
|
||||
@ -3813,6 +3844,9 @@ impl<'a, T> ExactSizeIterator for ExactChunksMut<'a, T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
unsafe impl<'a, T> TrustedLen for ExactChunksMut<'a, T> {}
|
||||
|
||||
#[unstable(feature = "exact_chunks", issue = "47115")]
|
||||
impl<'a, T> FusedIterator for ExactChunksMut<'a, T> {}
|
||||
|
||||
|
@ -3875,6 +3875,12 @@ impl<'a> Default for &'a str {
|
||||
fn default() -> &'a str { "" }
|
||||
}
|
||||
|
||||
#[stable(feature = "default_mut_str", since = "1.28.0")]
|
||||
impl<'a> Default for &'a mut str {
|
||||
/// Creates an empty mutable str
|
||||
fn default() -> &'a mut str { unsafe { from_utf8_unchecked_mut(&mut []) } }
|
||||
}
|
||||
|
||||
/// An iterator over the non-whitespace substrings of a string,
|
||||
/// separated by any amount of whitespace.
|
||||
///
|
||||
|
@ -268,6 +268,57 @@ impl Duration {
|
||||
#[inline]
|
||||
pub const fn subsec_nanos(&self) -> u32 { self.nanos }
|
||||
|
||||
/// Returns the total number of milliseconds contained by this `Duration`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # #![feature(duration_as_u128)]
|
||||
/// use std::time::Duration;
|
||||
///
|
||||
/// let duration = Duration::new(5, 730023852);
|
||||
/// assert_eq!(duration.as_millis(), 5730);
|
||||
/// ```
|
||||
#[unstable(feature = "duration_as_u128", issue = "50202")]
|
||||
#[inline]
|
||||
pub fn as_millis(&self) -> u128 {
|
||||
self.secs as u128 * MILLIS_PER_SEC as u128 + (self.nanos / NANOS_PER_MILLI) as u128
|
||||
}
|
||||
|
||||
/// Returns the total number of microseconds contained by this `Duration`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # #![feature(duration_as_u128)]
|
||||
/// use std::time::Duration;
|
||||
///
|
||||
/// let duration = Duration::new(5, 730023852);
|
||||
/// assert_eq!(duration.as_micros(), 5730023);
|
||||
/// ```
|
||||
#[unstable(feature = "duration_as_u128", issue = "50202")]
|
||||
#[inline]
|
||||
pub fn as_micros(&self) -> u128 {
|
||||
self.secs as u128 * MICROS_PER_SEC as u128 + (self.nanos / NANOS_PER_MICRO) as u128
|
||||
}
|
||||
|
||||
/// Returns the total number of nanoseconds contained by this `Duration`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # #![feature(duration_as_u128)]
|
||||
/// use std::time::Duration;
|
||||
///
|
||||
/// let duration = Duration::new(5, 730023852);
|
||||
/// assert_eq!(duration.as_nanos(), 5730023852);
|
||||
/// ```
|
||||
#[unstable(feature = "duration_as_u128", issue = "50202")]
|
||||
#[inline]
|
||||
pub fn as_nanos(&self) -> u128 {
|
||||
self.secs as u128 * NANOS_PER_SEC as u128 + self.nanos as u128
|
||||
}
|
||||
|
||||
/// Checked `Duration` addition. Computes `self + other`, returning [`None`]
|
||||
/// if overflow occurred.
|
||||
///
|
||||
|
@ -637,8 +637,8 @@ Erroneous code example:
|
||||
```compile_fail,E0152
|
||||
#![feature(lang_items)]
|
||||
|
||||
#[lang = "panic_fmt"]
|
||||
struct Foo; // error: duplicate lang item found: `panic_fmt`
|
||||
#[lang = "panic_impl"]
|
||||
struct Foo; // error: duplicate lang item found: `panic_impl`
|
||||
```
|
||||
|
||||
Lang items are already implemented in the standard library. Unless you are
|
||||
@ -824,7 +824,7 @@ A list of available external lang items is available in
|
||||
#![feature(lang_items)]
|
||||
|
||||
extern "C" {
|
||||
#[lang = "panic_fmt"] // ok!
|
||||
#[lang = "panic_impl"] // ok!
|
||||
fn cake();
|
||||
}
|
||||
```
|
||||
|
@ -134,9 +134,6 @@ pub struct Export {
|
||||
/// The visibility of the export.
|
||||
/// We include non-`pub` exports for hygienic macros that get used from extern crates.
|
||||
pub vis: ty::Visibility,
|
||||
/// True if from a `use` or and `extern crate`.
|
||||
/// Used in rustdoc.
|
||||
pub is_import: bool,
|
||||
}
|
||||
|
||||
impl CtorKind {
|
||||
|
@ -2433,7 +2433,7 @@ impl<'a> LoweringContext<'a> {
|
||||
self.with_hir_id_owner(new_id, |this| {
|
||||
let vis = match vis {
|
||||
hir::Visibility::Public => hir::Visibility::Public,
|
||||
hir::Visibility::Crate => hir::Visibility::Crate,
|
||||
hir::Visibility::Crate(sugar) => hir::Visibility::Crate(sugar),
|
||||
hir::Visibility::Inherited => hir::Visibility::Inherited,
|
||||
hir::Visibility::Restricted { ref path, id: _ } => {
|
||||
hir::Visibility::Restricted {
|
||||
@ -3704,7 +3704,7 @@ impl<'a> LoweringContext<'a> {
|
||||
) -> hir::Visibility {
|
||||
match v.node {
|
||||
VisibilityKind::Public => hir::Public,
|
||||
VisibilityKind::Crate(..) => hir::Visibility::Crate,
|
||||
VisibilityKind::Crate(sugar) => hir::Visibility::Crate(sugar),
|
||||
VisibilityKind::Restricted { ref path, id, .. } => hir::Visibility::Restricted {
|
||||
path: P(self.lower_path(id, path, ParamMode::Explicit)),
|
||||
id: if let Some(owner) = explicit_owner {
|
||||
|
@ -463,7 +463,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
|
||||
fn visit_vis(&mut self, visibility: &'hir Visibility) {
|
||||
match *visibility {
|
||||
Visibility::Public |
|
||||
Visibility::Crate |
|
||||
Visibility::Crate(_) |
|
||||
Visibility::Inherited => {}
|
||||
Visibility::Restricted { id, .. } => {
|
||||
self.insert(id, NodeVisibility(visibility));
|
||||
|
@ -35,7 +35,7 @@ use mir::mono::Linkage;
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
use syntax::codemap::{self, Spanned};
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use syntax::ast::{self, Ident, Name, NodeId, DUMMY_NODE_ID, AsmDialect};
|
||||
use syntax::ast::{self, CrateSugar, Ident, Name, NodeId, DUMMY_NODE_ID, AsmDialect};
|
||||
use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy, MetaItem};
|
||||
use syntax::attr::InlineAttr;
|
||||
use syntax::ext::hygiene::SyntaxContext;
|
||||
@ -1953,7 +1953,7 @@ pub struct PolyTraitRef {
|
||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||
pub enum Visibility {
|
||||
Public,
|
||||
Crate,
|
||||
Crate(CrateSugar),
|
||||
Restricted { path: P<Path>, id: NodeId },
|
||||
Inherited,
|
||||
}
|
||||
@ -1964,7 +1964,7 @@ impl Visibility {
|
||||
match self {
|
||||
&Public |
|
||||
&Inherited => false,
|
||||
&Crate |
|
||||
&Crate(_) |
|
||||
&Restricted { .. } => true,
|
||||
}
|
||||
}
|
||||
|
@ -801,15 +801,25 @@ impl<'a> State<'a> {
|
||||
|
||||
pub fn print_visibility(&mut self, vis: &hir::Visibility) -> io::Result<()> {
|
||||
match *vis {
|
||||
hir::Public => self.word_nbsp("pub"),
|
||||
hir::Visibility::Crate => self.word_nbsp("pub(crate)"),
|
||||
hir::Public => self.word_nbsp("pub")?,
|
||||
hir::Visibility::Crate(ast::CrateSugar::JustCrate) => self.word_nbsp("crate")?,
|
||||
hir::Visibility::Crate(ast::CrateSugar::PubCrate) => self.word_nbsp("pub(crate)")?,
|
||||
hir::Visibility::Restricted { ref path, .. } => {
|
||||
self.s.word("pub(")?;
|
||||
self.print_path(path, false)?;
|
||||
self.word_nbsp(")")
|
||||
if path.segments.len() == 1 && path.segments[0].name == keywords::Super.name() {
|
||||
// Special case: `super` can print like `pub(super)`.
|
||||
self.s.word("super")?;
|
||||
} else {
|
||||
// Everything else requires `in` at present.
|
||||
self.word_nbsp("in")?;
|
||||
self.print_path(path, false)?;
|
||||
}
|
||||
self.word_nbsp(")")?;
|
||||
}
|
||||
hir::Inherited => Ok(()),
|
||||
hir::Inherited => ()
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn print_defaultness(&mut self, defaultness: hir::Defaultness) -> io::Result<()> {
|
||||
|
@ -751,6 +751,11 @@ impl_stable_hash_for!(enum hir::ImplItemKind {
|
||||
Type(t)
|
||||
});
|
||||
|
||||
impl_stable_hash_for!(enum ::syntax::ast::CrateSugar {
|
||||
JustCrate,
|
||||
PubCrate,
|
||||
});
|
||||
|
||||
impl<'a> HashStable<StableHashingContext<'a>> for hir::Visibility {
|
||||
fn hash_stable<W: StableHasherResult>(&self,
|
||||
hcx: &mut StableHashingContext<'a>,
|
||||
@ -758,10 +763,12 @@ impl<'a> HashStable<StableHashingContext<'a>> for hir::Visibility {
|
||||
mem::discriminant(self).hash_stable(hcx, hasher);
|
||||
match *self {
|
||||
hir::Visibility::Public |
|
||||
hir::Visibility::Crate |
|
||||
hir::Visibility::Inherited => {
|
||||
// No fields to hash.
|
||||
}
|
||||
hir::Visibility::Crate(sugar) => {
|
||||
sugar.hash_stable(hcx, hasher);
|
||||
}
|
||||
hir::Visibility::Restricted { ref path, id } => {
|
||||
hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
|
||||
id.hash_stable(hcx, hasher);
|
||||
@ -1108,8 +1115,7 @@ impl_stable_hash_for!(struct hir::def::Export {
|
||||
ident,
|
||||
def,
|
||||
vis,
|
||||
span,
|
||||
is_import
|
||||
span
|
||||
});
|
||||
|
||||
impl<'a> HashStable<StableHashingContext<'a>>
|
||||
|
@ -284,7 +284,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> {
|
||||
fn has_allow_dead_code_or_lang_attr(tcx: TyCtxt,
|
||||
id: ast::NodeId,
|
||||
attrs: &[ast::Attribute]) -> bool {
|
||||
if attr::contains_name(attrs, "lang") {
|
||||
if attr::contains_name(attrs, "lang") || attr::contains_name(attrs, "panic_implementation") {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -185,6 +185,8 @@ pub fn extract(attrs: &[ast::Attribute]) -> Option<(Symbol, Span)> {
|
||||
if let Some(value) = attribute.value_str() {
|
||||
return Some((value, attribute.span));
|
||||
}
|
||||
} else if attribute.check_name("panic_implementation") {
|
||||
return Some((Symbol::intern("panic_impl"), attribute.span))
|
||||
}
|
||||
}
|
||||
|
||||
@ -299,7 +301,8 @@ language_item_table! {
|
||||
// lang item, but do not have it defined.
|
||||
PanicFnLangItem, "panic", panic_fn;
|
||||
PanicBoundsCheckFnLangItem, "panic_bounds_check", panic_bounds_check_fn;
|
||||
PanicFmtLangItem, "panic_fmt", panic_fmt;
|
||||
PanicInfoLangItem, "panic_info", panic_info;
|
||||
PanicImplLangItem, "panic_impl", panic_impl;
|
||||
|
||||
ExchangeMallocFnLangItem, "exchange_malloc", exchange_malloc_fn;
|
||||
BoxFreeFnLangItem, "box_free", box_free_fn;
|
||||
|
@ -936,16 +936,32 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||
span: Span,
|
||||
expr_ty: Ty<'tcx>)
|
||||
-> cmt_<'tcx> {
|
||||
debug!(
|
||||
"cat_rvalue_node(id={:?}, span={:?}, expr_ty={:?})",
|
||||
id,
|
||||
span,
|
||||
expr_ty,
|
||||
);
|
||||
let hir_id = self.tcx.hir.node_to_hir_id(id);
|
||||
let promotable = self.rvalue_promotable_map.as_ref().map(|m| m.contains(&hir_id.local_id))
|
||||
.unwrap_or(false);
|
||||
|
||||
debug!(
|
||||
"cat_rvalue_node: promotable = {:?}",
|
||||
promotable,
|
||||
);
|
||||
|
||||
// Always promote `[T; 0]` (even when e.g. borrowed mutably).
|
||||
let promotable = match expr_ty.sty {
|
||||
ty::TyArray(_, len) if len.assert_usize(self.tcx) == Some(0) => true,
|
||||
_ => promotable,
|
||||
};
|
||||
|
||||
debug!(
|
||||
"cat_rvalue_node: promotable = {:?} (2)",
|
||||
promotable,
|
||||
);
|
||||
|
||||
// Compute maximum lifetime of this rvalue. This is 'static if
|
||||
// we can promote to a constant, otherwise equal to enclosing temp
|
||||
// lifetime.
|
||||
|
@ -148,7 +148,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> {
|
||||
) }
|
||||
|
||||
weak_lang_items! {
|
||||
panic_fmt, PanicFmtLangItem, rust_begin_unwind;
|
||||
panic_impl, PanicImplLangItem, rust_begin_unwind;
|
||||
eh_personality, EhPersonalityLangItem, rust_eh_personality;
|
||||
eh_unwind_resume, EhUnwindResumeLangItem, rust_eh_unwind_resume;
|
||||
oom, OomLangItem, rust_oom;
|
||||
|
@ -1304,8 +1304,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
|
||||
"enable polonius-based borrow-checker"),
|
||||
codegen_time_graph: bool = (false, parse_bool, [UNTRACKED],
|
||||
"generate a graphical HTML report of time spent in codegen and LLVM"),
|
||||
trans_time_graph: bool = (false, parse_bool, [UNTRACKED],
|
||||
"generate a graphical HTML report of time spent in trans and LLVM"),
|
||||
thinlto: Option<bool> = (None, parse_opt_bool, [TRACKED],
|
||||
"enable ThinLTO when possible"),
|
||||
inline_in_all_cgus: Option<bool> = (None, parse_opt_bool, [TRACKED],
|
||||
|
@ -146,7 +146,7 @@ impl<'tcx> ProjectionTyCandidateSet<'tcx> {
|
||||
// was not used). On other paths, it is not assigned,
|
||||
// and hence if those paths *could* reach the code that
|
||||
// comes after the match, this fn would not compile.
|
||||
let convert_to_ambigious;
|
||||
let convert_to_ambiguous;
|
||||
|
||||
match self {
|
||||
None => {
|
||||
@ -169,10 +169,10 @@ impl<'tcx> ProjectionTyCandidateSet<'tcx> {
|
||||
// clauses are the safer choice. See the comment on
|
||||
// `select::SelectionCandidate` and #21974 for more details.
|
||||
match (current, candidate) {
|
||||
(ParamEnv(..), ParamEnv(..)) => convert_to_ambigious = (),
|
||||
(ParamEnv(..), ParamEnv(..)) => convert_to_ambiguous = (),
|
||||
(ParamEnv(..), _) => return false,
|
||||
(_, ParamEnv(..)) => { unreachable!(); }
|
||||
(_, _) => convert_to_ambigious = (),
|
||||
(_, _) => convert_to_ambiguous = (),
|
||||
}
|
||||
}
|
||||
|
||||
@ -183,7 +183,7 @@ impl<'tcx> ProjectionTyCandidateSet<'tcx> {
|
||||
|
||||
// We only ever get here when we moved from a single candidate
|
||||
// to ambiguous.
|
||||
let () = convert_to_ambigious;
|
||||
let () = convert_to_ambiguous;
|
||||
*self = Ambiguous;
|
||||
false
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ impl<'cx, 'gcx, 'tcx> At<'cx, 'gcx, 'tcx> {
|
||||
/// normalized. If you don't care about regions, you should prefer
|
||||
/// `normalize_erasing_regions`, which is more efficient.
|
||||
///
|
||||
/// If the normalization succeeds and is unambigious, returns back
|
||||
/// If the normalization succeeds and is unambiguous, returns back
|
||||
/// the normalized value along with various outlives relations (in
|
||||
/// the form of obligations that must be discharged).
|
||||
///
|
||||
|
@ -270,7 +270,7 @@ impl Visibility {
|
||||
pub fn from_hir(visibility: &hir::Visibility, id: NodeId, tcx: TyCtxt) -> Self {
|
||||
match *visibility {
|
||||
hir::Public => Visibility::Public,
|
||||
hir::Visibility::Crate => Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)),
|
||||
hir::Visibility::Crate(_) => Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)),
|
||||
hir::Visibility::Restricted { ref path, .. } => match path.def {
|
||||
// If there is no resolution, `resolve` will have already reported an error, so
|
||||
// assume that the visibility is public to avoid reporting more privacy errors.
|
||||
|
@ -625,6 +625,11 @@ fn link_natively(sess: &Session,
|
||||
if let Some(args) = sess.target.target.options.pre_link_args.get(&flavor) {
|
||||
cmd.args(args);
|
||||
}
|
||||
if let Some(args) = sess.target.target.options.pre_link_args_crt.get(&flavor) {
|
||||
if sess.crt_static() {
|
||||
cmd.args(args);
|
||||
}
|
||||
}
|
||||
if let Some(ref args) = sess.opts.debugging_opts.pre_link_args {
|
||||
cmd.args(args);
|
||||
}
|
||||
@ -639,6 +644,12 @@ fn link_natively(sess: &Session,
|
||||
cmd.arg(root.join(obj));
|
||||
}
|
||||
|
||||
if crate_type == config::CrateTypeExecutable && sess.crt_static() {
|
||||
for obj in &sess.target.target.options.pre_link_objects_exe_crt {
|
||||
cmd.arg(root.join(obj));
|
||||
}
|
||||
}
|
||||
|
||||
if sess.target.target.options.is_like_emscripten {
|
||||
cmd.arg("-s");
|
||||
cmd.arg(if sess.panic_strategy() == PanicStrategy::Abort {
|
||||
@ -660,6 +671,11 @@ fn link_natively(sess: &Session,
|
||||
for obj in &sess.target.target.options.post_link_objects {
|
||||
cmd.arg(root.join(obj));
|
||||
}
|
||||
if sess.crt_static() {
|
||||
for obj in &sess.target.target.options.post_link_objects_crt {
|
||||
cmd.arg(root.join(obj));
|
||||
}
|
||||
}
|
||||
if let Some(args) = sess.target.target.options.post_link_args.get(&flavor) {
|
||||
cmd.args(args);
|
||||
}
|
||||
|
@ -191,14 +191,23 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||
|
||||
mir::TerminatorKind::SwitchInt { ref discr, switch_ty, ref values, ref targets } => {
|
||||
let discr = self.codegen_operand(&bx, discr);
|
||||
if switch_ty == bx.tcx().types.bool {
|
||||
if targets.len() == 2 {
|
||||
// If there are two targets, emit br instead of switch
|
||||
let lltrue = llblock(self, targets[0]);
|
||||
let llfalse = llblock(self, targets[1]);
|
||||
if let [0] = values[..] {
|
||||
bx.cond_br(discr.immediate(), llfalse, lltrue);
|
||||
if switch_ty == bx.tcx().types.bool {
|
||||
// Don't generate trivial icmps when switching on bool
|
||||
if let [0] = values[..] {
|
||||
bx.cond_br(discr.immediate(), llfalse, lltrue);
|
||||
} else {
|
||||
assert_eq!(&values[..], &[1]);
|
||||
bx.cond_br(discr.immediate(), lltrue, llfalse);
|
||||
}
|
||||
} else {
|
||||
assert_eq!(&values[..], &[1]);
|
||||
bx.cond_br(discr.immediate(), lltrue, llfalse);
|
||||
let switch_llty = bx.cx.layout_of(switch_ty).immediate_llvm_type(bx.cx);
|
||||
let llval = C_uint_big(switch_llty, values[0]);
|
||||
let cmp = bx.icmp(llvm::IntEQ, discr.immediate(), llval);
|
||||
bx.cond_br(cmp, lltrue, llfalse);
|
||||
}
|
||||
} else {
|
||||
let (otherwise, targets) = targets.split_last().unwrap();
|
||||
|
@ -1548,72 +1548,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedBrokenConst {
|
||||
}
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub UNNECESSARY_EXTERN_CRATES,
|
||||
Allow,
|
||||
"suggest removing `extern crate` for the 2018 edition"
|
||||
}
|
||||
|
||||
pub struct ExternCrate(/* depth */ u32);
|
||||
|
||||
impl ExternCrate {
|
||||
pub fn new() -> Self {
|
||||
ExternCrate(0)
|
||||
}
|
||||
}
|
||||
|
||||
impl LintPass for ExternCrate {
|
||||
fn get_lints(&self) -> LintArray {
|
||||
lint_array!(UNNECESSARY_EXTERN_CRATES)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExternCrate {
|
||||
fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
|
||||
if !cx.tcx.features().extern_absolute_paths {
|
||||
return
|
||||
}
|
||||
if let hir::ItemExternCrate(ref orig) = it.node {
|
||||
if it.attrs.iter().any(|a| a.check_name("macro_use")) {
|
||||
return
|
||||
}
|
||||
let mut err = cx.struct_span_lint(UNNECESSARY_EXTERN_CRATES,
|
||||
it.span, "`extern crate` is unnecessary in the new edition");
|
||||
if it.vis == hir::Visibility::Public || self.0 > 1 || orig.is_some() {
|
||||
let pub_ = if it.vis == hir::Visibility::Public {
|
||||
"pub "
|
||||
} else {
|
||||
""
|
||||
};
|
||||
|
||||
let help = format!("use `{}use`", pub_);
|
||||
|
||||
if let Some(orig) = orig {
|
||||
err.span_suggestion(it.span, &help,
|
||||
format!("{}use {} as {};", pub_, orig, it.name));
|
||||
} else {
|
||||
err.span_suggestion(it.span, &help,
|
||||
format!("{}use {};", pub_, it.name));
|
||||
}
|
||||
} else {
|
||||
err.span_suggestion(it.span, "remove it", "".into());
|
||||
}
|
||||
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
|
||||
fn check_mod(&mut self, _: &LateContext, _: &hir::Mod,
|
||||
_: Span, _: ast::NodeId) {
|
||||
self.0 += 1;
|
||||
}
|
||||
|
||||
fn check_mod_post(&mut self, _: &LateContext, _: &hir::Mod,
|
||||
_: Span, _: ast::NodeId) {
|
||||
self.0 += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// Lint for trait and lifetime bounds that don't depend on type parameters
|
||||
/// which either do nothing, or stop the item from being used.
|
||||
pub struct TrivialConstraints;
|
||||
|
@ -145,7 +145,6 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
|
||||
TypeLimits,
|
||||
MissingDoc,
|
||||
MissingDebugImplementations,
|
||||
ExternCrate,
|
||||
);
|
||||
|
||||
add_lint_group!(sess,
|
||||
@ -185,7 +184,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
|
||||
"rust_2018_idioms",
|
||||
BARE_TRAIT_OBJECTS,
|
||||
UNREACHABLE_PUB,
|
||||
UNNECESSARY_EXTERN_CRATES);
|
||||
UNUSED_EXTERN_CRATES);
|
||||
|
||||
// Guidelines for creating a future incompatibility lint:
|
||||
//
|
||||
|
@ -665,7 +665,6 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
def: def,
|
||||
vis: ty::Visibility::Public,
|
||||
span: DUMMY_SP,
|
||||
is_import: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -705,7 +704,6 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
ident: Ident::from_interned_str(self.item_name(child_index)),
|
||||
vis: self.get_visibility(child_index),
|
||||
span: self.entry(child_index).span.decode((self, sess)),
|
||||
is_import: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -722,8 +720,7 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
(self.get_def(child_index), def_key.disambiguated_data.data.get_opt_name()) {
|
||||
let ident = Ident::from_interned_str(name);
|
||||
let vis = self.get_visibility(child_index);
|
||||
let is_import = false;
|
||||
callback(def::Export { def, ident, vis, span, is_import });
|
||||
callback(def::Export { def, ident, vis, span });
|
||||
// For non-re-export structs and variants add their constructors to children.
|
||||
// Re-export lists automatically contain constructors when necessary.
|
||||
match def {
|
||||
@ -734,7 +731,7 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
callback(def::Export {
|
||||
def: ctor_def,
|
||||
vis: self.get_visibility(ctor_def_id.index),
|
||||
ident, span, is_import,
|
||||
ident, span,
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -744,7 +741,7 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
let ctor_kind = self.get_ctor_kind(child_index);
|
||||
let ctor_def = Def::VariantCtor(def_id, ctor_kind);
|
||||
let vis = self.get_visibility(child_index);
|
||||
callback(def::Export { def: ctor_def, ident, vis, span, is_import });
|
||||
callback(def::Export { def: ctor_def, ident, vis, span });
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
@ -362,8 +362,8 @@ fn unsafe_derive_on_repr_packed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: D
|
||||
format!("#[derive] can't be used on a #[repr(packed)] struct with \
|
||||
type parameters (error E0133)")
|
||||
} else {
|
||||
format!("#[derive] can't be used on a non-Copy #[repr(packed)] struct \
|
||||
(error E0133)")
|
||||
format!("#[derive] can't be used on a #[repr(packed)] struct that \
|
||||
does not derive Copy (error E0133)")
|
||||
};
|
||||
tcx.lint_node(SAFE_PACKED_BORROWS,
|
||||
lint_node_id,
|
||||
|
@ -150,6 +150,23 @@ impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> {
|
||||
span.allows_unstable();
|
||||
}
|
||||
}
|
||||
|
||||
/// While the `ExprUseVisitor` walks, we will identify which
|
||||
/// expressions are borrowed, and insert their ids into this
|
||||
/// table. Actually, we insert the "borrow-id", which is normally
|
||||
/// the id of the expession being borrowed: but in the case of
|
||||
/// `ref mut` borrows, the `id` of the pattern is
|
||||
/// inserted. Therefore later we remove that entry from the table
|
||||
/// and transfer it over to the value being matched. This will
|
||||
/// then prevent said value from being promoted.
|
||||
fn remove_mut_rvalue_borrow(&mut self, pat: &hir::Pat) -> bool {
|
||||
let mut any_removed = false;
|
||||
pat.walk(|p| {
|
||||
any_removed |= self.mut_rvalue_borrows.remove(&p.id);
|
||||
true
|
||||
});
|
||||
any_removed
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> {
|
||||
@ -200,9 +217,15 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> {
|
||||
fn visit_stmt(&mut self, stmt: &'tcx hir::Stmt) {
|
||||
match stmt.node {
|
||||
hir::StmtDecl(ref decl, _) => {
|
||||
match decl.node {
|
||||
hir::DeclLocal(_) => {
|
||||
match &decl.node {
|
||||
hir::DeclLocal(local) => {
|
||||
self.promotable = false;
|
||||
|
||||
if self.remove_mut_rvalue_borrow(&local.pat) {
|
||||
if let Some(init) = &local.init {
|
||||
self.mut_rvalue_borrows.insert(init.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Item statements are allowed
|
||||
hir::DeclItem(_) => {}
|
||||
@ -229,9 +252,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> {
|
||||
// patterns and set that on the discriminator.
|
||||
let mut mut_borrow = false;
|
||||
for pat in arms.iter().flat_map(|arm| &arm.pats) {
|
||||
if self.mut_rvalue_borrows.remove(&pat.id) {
|
||||
mut_borrow = true;
|
||||
}
|
||||
mut_borrow = self.remove_mut_rvalue_borrow(pat);
|
||||
}
|
||||
if mut_borrow {
|
||||
self.mut_rvalue_borrows.insert(discr.id);
|
||||
@ -498,6 +519,14 @@ impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for CheckCrateVisitor<'a, 'gcx> {
|
||||
_loan_region: ty::Region<'tcx>,
|
||||
bk: ty::BorrowKind,
|
||||
loan_cause: euv::LoanCause) {
|
||||
debug!(
|
||||
"borrow(borrow_id={:?}, cmt={:?}, bk={:?}, loan_cause={:?})",
|
||||
borrow_id,
|
||||
cmt,
|
||||
bk,
|
||||
loan_cause,
|
||||
);
|
||||
|
||||
// Kind of hacky, but we allow Unsafe coercions in constants.
|
||||
// These occur when we convert a &T or *T to a *U, as well as
|
||||
// when making a thin pointer (e.g., `*T`) into a fat pointer
|
||||
|
@ -803,7 +803,6 @@ impl<'a> Resolver<'a> {
|
||||
def: def,
|
||||
vis: ty::Visibility::Public,
|
||||
span: item.span,
|
||||
is_import: false,
|
||||
});
|
||||
} else {
|
||||
self.unused_macros.insert(def_id);
|
||||
|
@ -1008,7 +1008,6 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
||||
def: def,
|
||||
span: binding.span,
|
||||
vis: binding.vis,
|
||||
is_import: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,8 @@ pub fn opts() -> TargetOptions {
|
||||
|
||||
// Make sure that the linker/gcc really don't pull in anything, including
|
||||
// default objects, libs, etc.
|
||||
base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-nostdlib".to_string());
|
||||
base.pre_link_args_crt.insert(LinkerFlavor::Gcc, Vec::new());
|
||||
base.pre_link_args_crt.get_mut(&LinkerFlavor::Gcc).unwrap().push("-nostdlib".to_string());
|
||||
|
||||
// At least when this was tested, the linker would not add the
|
||||
// `GNU_EH_FRAME` program header to executables generated, which is required
|
||||
@ -55,9 +56,9 @@ pub fn opts() -> TargetOptions {
|
||||
//
|
||||
// Each target directory for musl has these object files included in it so
|
||||
// they'll be included from there.
|
||||
base.pre_link_objects_exe.push("crt1.o".to_string());
|
||||
base.pre_link_objects_exe.push("crti.o".to_string());
|
||||
base.post_link_objects.push("crtn.o".to_string());
|
||||
base.pre_link_objects_exe_crt.push("crt1.o".to_string());
|
||||
base.pre_link_objects_exe_crt.push("crti.o".to_string());
|
||||
base.post_link_objects_crt.push("crtn.o".to_string());
|
||||
|
||||
// These targets statically link libc by default
|
||||
base.crt_static_default = true;
|
||||
|
@ -426,12 +426,13 @@ pub struct TargetOptions {
|
||||
/// Linker to invoke
|
||||
pub linker: Option<String>,
|
||||
|
||||
/// Linker arguments that are unconditionally passed *before* any
|
||||
/// user-defined libraries.
|
||||
pub pre_link_args: LinkArgs,
|
||||
/// Linker arguments that are passed *before* any user-defined libraries.
|
||||
pub pre_link_args: LinkArgs, // ... unconditionally
|
||||
pub pre_link_args_crt: LinkArgs, // ... when linking with a bundled crt
|
||||
/// Objects to link before all others, always found within the
|
||||
/// sysroot folder.
|
||||
pub pre_link_objects_exe: Vec<String>, // ... when linking an executable
|
||||
pub pre_link_objects_exe: Vec<String>, // ... when linking an executable, unconditionally
|
||||
pub pre_link_objects_exe_crt: Vec<String>, // ... when linking an executable with a bundled crt
|
||||
pub pre_link_objects_dll: Vec<String>, // ... when linking a dylib
|
||||
/// Linker arguments that are unconditionally passed after any
|
||||
/// user-defined but before post_link_objects. Standard platform
|
||||
@ -439,7 +440,8 @@ pub struct TargetOptions {
|
||||
pub late_link_args: LinkArgs,
|
||||
/// Objects to link after all others, always found within the
|
||||
/// sysroot folder.
|
||||
pub post_link_objects: Vec<String>,
|
||||
pub post_link_objects: Vec<String>, // ... unconditionally
|
||||
pub post_link_objects_crt: Vec<String>, // ... when linking with a bundled crt
|
||||
/// Linker arguments that are unconditionally passed *after* any
|
||||
/// user-defined libraries.
|
||||
pub post_link_args: LinkArgs,
|
||||
@ -639,6 +641,7 @@ impl Default for TargetOptions {
|
||||
is_builtin: false,
|
||||
linker: option_env!("CFG_DEFAULT_LINKER").map(|s| s.to_string()),
|
||||
pre_link_args: LinkArgs::new(),
|
||||
pre_link_args_crt: LinkArgs::new(),
|
||||
post_link_args: LinkArgs::new(),
|
||||
asm_args: Vec::new(),
|
||||
cpu: "generic".to_string(),
|
||||
@ -672,8 +675,10 @@ impl Default for TargetOptions {
|
||||
position_independent_executables: false,
|
||||
relro_level: RelroLevel::None,
|
||||
pre_link_objects_exe: Vec::new(),
|
||||
pre_link_objects_exe_crt: Vec::new(),
|
||||
pre_link_objects_dll: Vec::new(),
|
||||
post_link_objects: Vec::new(),
|
||||
post_link_objects_crt: Vec::new(),
|
||||
late_link_args: LinkArgs::new(),
|
||||
link_env: Vec::new(),
|
||||
archive_format: "gnu".to_string(),
|
||||
@ -892,10 +897,13 @@ impl Target {
|
||||
key!(is_builtin, bool);
|
||||
key!(linker, optional);
|
||||
key!(pre_link_args, link_args);
|
||||
key!(pre_link_args_crt, link_args);
|
||||
key!(pre_link_objects_exe, list);
|
||||
key!(pre_link_objects_exe_crt, list);
|
||||
key!(pre_link_objects_dll, list);
|
||||
key!(late_link_args, link_args);
|
||||
key!(post_link_objects, list);
|
||||
key!(post_link_objects_crt, list);
|
||||
key!(post_link_args, link_args);
|
||||
key!(link_env, env);
|
||||
key!(asm_args, list);
|
||||
@ -1097,10 +1105,13 @@ impl ToJson for Target {
|
||||
target_option_val!(is_builtin);
|
||||
target_option_val!(linker);
|
||||
target_option_val!(link_args - pre_link_args);
|
||||
target_option_val!(link_args - pre_link_args_crt);
|
||||
target_option_val!(pre_link_objects_exe);
|
||||
target_option_val!(pre_link_objects_exe_crt);
|
||||
target_option_val!(pre_link_objects_dll);
|
||||
target_option_val!(link_args - late_link_args);
|
||||
target_option_val!(post_link_objects);
|
||||
target_option_val!(post_link_objects_crt);
|
||||
target_option_val!(link_args - post_link_args);
|
||||
target_option_val!(env - link_env);
|
||||
target_option_val!(asm_args);
|
||||
|
@ -195,7 +195,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
let ty_string = self.ty_to_string(actual);
|
||||
let is_method = mode == Mode::MethodCall;
|
||||
let mut suggestion = None;
|
||||
let type_str = if is_method {
|
||||
let item_kind = if is_method {
|
||||
"method"
|
||||
} else if actual.is_enum() {
|
||||
if let TyAdt(ref adt_def, _) = actual.sty {
|
||||
@ -235,7 +235,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
span,
|
||||
E0689,
|
||||
"can't call {} `{}` on ambiguous numeric type `{}`",
|
||||
type_str,
|
||||
item_kind,
|
||||
item_name,
|
||||
ty_string
|
||||
);
|
||||
@ -284,12 +284,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
span,
|
||||
E0599,
|
||||
"no {} named `{}` found for type `{}` in the current scope",
|
||||
type_str,
|
||||
item_kind,
|
||||
item_name,
|
||||
ty_string
|
||||
);
|
||||
if let Some(suggestion) = suggestion {
|
||||
err.note(&format!("did you mean `{}::{}`?", type_str, suggestion));
|
||||
err.note(&format!("did you mean `{}::{}`?", ty_string, suggestion));
|
||||
}
|
||||
err
|
||||
}
|
||||
@ -301,7 +301,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
if let Some(full_sp) = tcx.hir.span_if_local(def.did) {
|
||||
let def_sp = tcx.sess.codemap().def_span(full_sp);
|
||||
err.span_label(def_sp, format!("{} `{}` not found {}",
|
||||
type_str,
|
||||
item_kind,
|
||||
item_name,
|
||||
if def.is_enum() && !is_method {
|
||||
"here"
|
||||
@ -355,7 +355,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
err.span_label(span, format!("{} not found in `{}`", type_str, ty_string));
|
||||
err.span_label(span, format!("{} not found in `{}`", item_kind, ty_string));
|
||||
}
|
||||
|
||||
if self.is_fn_ty(&rcvr_ty, span) {
|
||||
|
@ -96,7 +96,7 @@ use rustc::middle::region;
|
||||
use rustc::mir::interpret::{GlobalId};
|
||||
use rustc::ty::subst::{UnpackedKind, Subst, Substs};
|
||||
use rustc::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine};
|
||||
use rustc::ty::{self, Ty, TyCtxt, GenericParamDefKind, Visibility, ToPredicate};
|
||||
use rustc::ty::{self, Ty, TyCtxt, GenericParamDefKind, Visibility, ToPredicate, RegionKind};
|
||||
use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
|
||||
use rustc::ty::fold::TypeFoldable;
|
||||
use rustc::ty::maps::Providers;
|
||||
@ -130,7 +130,7 @@ use syntax_pos::{self, BytePos, Span, MultiSpan};
|
||||
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
|
||||
use rustc::hir::itemlikevisit::ItemLikeVisitor;
|
||||
use rustc::hir::map::Node;
|
||||
use rustc::hir::{self, PatKind};
|
||||
use rustc::hir::{self, PatKind, Item_};
|
||||
use rustc::middle::lang_items;
|
||||
|
||||
mod autoderef;
|
||||
@ -1129,6 +1129,60 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
|
||||
}
|
||||
}
|
||||
|
||||
// Check that a function marked as `#[panic_implementation]` has signature `fn(&PanicInfo) -> !`
|
||||
if let Some(panic_impl_did) = fcx.tcx.lang_items().panic_impl() {
|
||||
if panic_impl_did == fn_hir_id.owner_def_id() {
|
||||
if let Some(panic_info_did) = fcx.tcx.lang_items().panic_info() {
|
||||
if declared_ret_ty.sty != ty::TyNever {
|
||||
fcx.tcx.sess.span_err(
|
||||
decl.output.span(),
|
||||
"return type should be `!`",
|
||||
);
|
||||
}
|
||||
|
||||
let inputs = fn_sig.inputs();
|
||||
let span = fcx.tcx.hir.span(fn_id);
|
||||
if inputs.len() == 1 {
|
||||
let arg_is_panic_info = match inputs[0].sty {
|
||||
ty::TyRef(region, ty, mutbl) => match ty.sty {
|
||||
ty::TyAdt(ref adt, _) => {
|
||||
adt.did == panic_info_did &&
|
||||
mutbl == hir::Mutability::MutImmutable &&
|
||||
*region != RegionKind::ReStatic
|
||||
},
|
||||
_ => false,
|
||||
},
|
||||
_ => false,
|
||||
};
|
||||
|
||||
if !arg_is_panic_info {
|
||||
fcx.tcx.sess.span_err(
|
||||
decl.inputs[0].span,
|
||||
"argument should be `&PanicInfo`",
|
||||
);
|
||||
}
|
||||
|
||||
if let Node::NodeItem(item) = fcx.tcx.hir.get(fn_id) {
|
||||
if let Item_::ItemFn(_, _, _, _, ref generics, _) = item.node {
|
||||
if !generics.params.is_empty() {
|
||||
fcx.tcx.sess.span_err(
|
||||
span,
|
||||
"`#[panic_implementation]` function should have no type \
|
||||
parameters",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fcx.tcx.sess.span_err(span, "function should have one argument");
|
||||
}
|
||||
} else {
|
||||
fcx.tcx.sess.err("language item required, but not found: `panic_info`");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
(fcx, gen_ty)
|
||||
}
|
||||
|
||||
|
@ -14,11 +14,46 @@ use rustc::ty::TyCtxt;
|
||||
use syntax::ast;
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
|
||||
use rustc::hir::def_id::LOCAL_CRATE;
|
||||
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
|
||||
use rustc::hir::itemlikevisit::ItemLikeVisitor;
|
||||
use rustc::hir::print::visibility_qualified;
|
||||
use rustc::hir;
|
||||
use rustc::util::nodemap::DefIdSet;
|
||||
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
|
||||
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
|
||||
let mut used_trait_imports = DefIdSet();
|
||||
for &body_id in tcx.hir.krate().bodies.keys() {
|
||||
let item_def_id = tcx.hir.body_owner_def_id(body_id);
|
||||
let imports = tcx.used_trait_imports(item_def_id);
|
||||
debug!("GatherVisitor: item_def_id={:?} with imports {:#?}", item_def_id, imports);
|
||||
used_trait_imports.extend(imports.iter());
|
||||
}
|
||||
|
||||
let mut visitor = CheckVisitor { tcx, used_trait_imports };
|
||||
tcx.hir.krate().visit_all_item_likes(&mut visitor);
|
||||
|
||||
unused_crates_lint(tcx);
|
||||
}
|
||||
|
||||
impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CheckVisitor<'a, 'tcx> {
|
||||
fn visit_item(&mut self, item: &hir::Item) {
|
||||
if item.vis == hir::Public || item.span == DUMMY_SP {
|
||||
return;
|
||||
}
|
||||
if let hir::ItemUse(ref path, _) = item.node {
|
||||
self.check_import(item.id, path.span);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
|
||||
}
|
||||
|
||||
fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
|
||||
}
|
||||
}
|
||||
|
||||
struct CheckVisitor<'a, 'tcx: 'a> {
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
used_trait_imports: DefIdSet,
|
||||
@ -45,13 +80,131 @@ impl<'a, 'tcx> CheckVisitor<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CheckVisitor<'a, 'tcx> {
|
||||
fn visit_item(&mut self, item: &hir::Item) {
|
||||
if item.vis == hir::Public || item.span == DUMMY_SP {
|
||||
return;
|
||||
fn unused_crates_lint<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) {
|
||||
let lint = lint::builtin::UNUSED_EXTERN_CRATES;
|
||||
|
||||
// Collect first the crates that are completely unused. These we
|
||||
// can always suggest removing (no matter which edition we are
|
||||
// in).
|
||||
let unused_extern_crates: FxHashMap<DefId, Span> =
|
||||
tcx.maybe_unused_extern_crates(LOCAL_CRATE)
|
||||
.iter()
|
||||
.filter(|&&(def_id, _)| {
|
||||
// The `def_id` here actually was calculated during resolution (at least
|
||||
// at the time of this writing) and is being shipped to us via a side
|
||||
// channel of the tcx. There may have been extra expansion phases,
|
||||
// however, which ended up removing the `def_id` *after* expansion such
|
||||
// as the `ReplaceBodyWithLoop` pass (which is a bit of a hack, but hey)
|
||||
//
|
||||
// As a result we need to verify that `def_id` is indeed still valid for
|
||||
// our AST and actually present in the HIR map. If it's not there then
|
||||
// there's safely nothing to warn about, and otherwise we carry on with
|
||||
// our execution.
|
||||
//
|
||||
// Note that if we carry through to the `extern_mod_stmt_cnum` query
|
||||
// below it'll cause a panic because `def_id` is actually bogus at this
|
||||
// point in time otherwise.
|
||||
if let Some(id) = tcx.hir.as_local_node_id(def_id) {
|
||||
if tcx.hir.find(id).is_none() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
})
|
||||
.filter(|&&(def_id, _)| {
|
||||
let cnum = tcx.extern_mod_stmt_cnum(def_id).unwrap();
|
||||
!tcx.is_compiler_builtins(cnum)
|
||||
&& !tcx.is_panic_runtime(cnum)
|
||||
&& !tcx.has_global_allocator(cnum)
|
||||
})
|
||||
.cloned()
|
||||
.collect();
|
||||
|
||||
// Collect all the extern crates (in a reliable order).
|
||||
let mut crates_to_lint = vec![];
|
||||
tcx.hir.krate().visit_all_item_likes(&mut CollectExternCrateVisitor {
|
||||
tcx,
|
||||
crates_to_lint: &mut crates_to_lint,
|
||||
});
|
||||
|
||||
for extern_crate in &crates_to_lint {
|
||||
assert!(extern_crate.def_id.is_local());
|
||||
|
||||
// If the crate is fully unused, we suggest removing it altogether.
|
||||
// We do this in any edition.
|
||||
if let Some(&span) = unused_extern_crates.get(&extern_crate.def_id) {
|
||||
assert_eq!(extern_crate.def_id.krate, LOCAL_CRATE);
|
||||
let hir_id = tcx.hir.definitions().def_index_to_hir_id(extern_crate.def_id.index);
|
||||
let id = tcx.hir.hir_to_node_id(hir_id);
|
||||
let msg = "unused extern crate";
|
||||
tcx.struct_span_lint_node(lint, id, span, msg)
|
||||
.span_suggestion_short(span, "remove it", "".to_string())
|
||||
.emit();
|
||||
continue;
|
||||
}
|
||||
if let hir::ItemUse(ref path, _) = item.node {
|
||||
self.check_import(item.id, path.span);
|
||||
|
||||
// If we are not in Rust 2018 edition, then we don't make any further
|
||||
// suggestions.
|
||||
if !tcx.sess.rust_2018() {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the extern crate has any attributes, they may have funky
|
||||
// semantics we can't faithfully represent using `use` (most
|
||||
// notably `#[macro_use]`). Ignore it.
|
||||
if !tcx.get_attrs(extern_crate.def_id).is_empty() {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Otherwise, we can convert it into a `use` of some kind.
|
||||
let hir_id = tcx.hir.definitions().def_index_to_hir_id(extern_crate.def_id.index);
|
||||
let id = tcx.hir.hir_to_node_id(hir_id);
|
||||
let item = tcx.hir.expect_item(id);
|
||||
let msg = "`extern crate` is not idiomatic in the new edition";
|
||||
let help = format!(
|
||||
"convert it to a `{}`",
|
||||
visibility_qualified(&item.vis, "use")
|
||||
);
|
||||
let base_replacement = match extern_crate.orig_name {
|
||||
Some(orig_name) => format!("use {} as {};", orig_name, item.name),
|
||||
None => format!("use {};", item.name),
|
||||
};
|
||||
let replacement = visibility_qualified(&item.vis, &base_replacement);
|
||||
tcx.struct_span_lint_node(lint, id, extern_crate.span, msg)
|
||||
.span_suggestion_short(extern_crate.span, &help, replacement)
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
|
||||
struct CollectExternCrateVisitor<'a, 'tcx: 'a> {
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
crates_to_lint: &'a mut Vec<ExternCrateToLint>,
|
||||
}
|
||||
|
||||
struct ExternCrateToLint {
|
||||
/// def-id of the extern crate
|
||||
def_id: DefId,
|
||||
|
||||
/// span from the item
|
||||
span: Span,
|
||||
|
||||
/// if `Some`, then this is renamed (`extern crate orig_name as
|
||||
/// crate_name`), and -- perhaps surprisingly -- this stores the
|
||||
/// *original* name (`item.name` will contain the new name)
|
||||
orig_name: Option<ast::Name>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CollectExternCrateVisitor<'a, 'tcx> {
|
||||
fn visit_item(&mut self, item: &hir::Item) {
|
||||
if let hir::ItemExternCrate(orig_name) = item.node {
|
||||
let extern_crate_def_id = self.tcx.hir.local_def_id(item.id);
|
||||
self.crates_to_lint.push(
|
||||
ExternCrateToLint {
|
||||
def_id: extern_crate_def_id,
|
||||
span: item.span,
|
||||
orig_name,
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -62,53 +215,3 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CheckVisitor<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
|
||||
let mut used_trait_imports = DefIdSet();
|
||||
for &body_id in tcx.hir.krate().bodies.keys() {
|
||||
let item_def_id = tcx.hir.body_owner_def_id(body_id);
|
||||
let imports = tcx.used_trait_imports(item_def_id);
|
||||
debug!("GatherVisitor: item_def_id={:?} with imports {:#?}", item_def_id, imports);
|
||||
used_trait_imports.extend(imports.iter());
|
||||
}
|
||||
|
||||
let mut visitor = CheckVisitor { tcx, used_trait_imports };
|
||||
tcx.hir.krate().visit_all_item_likes(&mut visitor);
|
||||
|
||||
for &(def_id, span) in tcx.maybe_unused_extern_crates(LOCAL_CRATE).iter() {
|
||||
// The `def_id` here actually was calculated during resolution (at least
|
||||
// at the time of this writing) and is being shipped to us via a side
|
||||
// channel of the tcx. There may have been extra expansion phases,
|
||||
// however, which ended up removing the `def_id` *after* expansion such
|
||||
// as the `ReplaceBodyWithLoop` pass (which is a bit of a hack, but hey)
|
||||
//
|
||||
// As a result we need to verify that `def_id` is indeed still valid for
|
||||
// our AST and actually present in the HIR map. If it's not there then
|
||||
// there's safely nothing to warn about, and otherwise we carry on with
|
||||
// our execution.
|
||||
//
|
||||
// Note that if we carry through to the `extern_mod_stmt_cnum` query
|
||||
// below it'll cause a panic because `def_id` is actually bogus at this
|
||||
// point in time otherwise.
|
||||
if let Some(id) = tcx.hir.as_local_node_id(def_id) {
|
||||
if tcx.hir.find(id).is_none() {
|
||||
continue
|
||||
}
|
||||
}
|
||||
let cnum = tcx.extern_mod_stmt_cnum(def_id).unwrap();
|
||||
if tcx.is_compiler_builtins(cnum) {
|
||||
continue
|
||||
}
|
||||
if tcx.is_panic_runtime(cnum) {
|
||||
continue
|
||||
}
|
||||
if tcx.has_global_allocator(cnum) {
|
||||
continue
|
||||
}
|
||||
assert_eq!(def_id.krate, LOCAL_CRATE);
|
||||
let hir_id = tcx.hir.definitions().def_index_to_hir_id(def_id.index);
|
||||
let id = tcx.hir.hir_to_node_id(hir_id);
|
||||
let lint = lint::builtin::UNUSED_EXTERN_CRATES;
|
||||
let msg = "unused extern crate";
|
||||
tcx.lint_node(lint, id, span, msg);
|
||||
}
|
||||
}
|
||||
|
@ -57,6 +57,7 @@ use std::rc::Rc;
|
||||
use std::cell::RefCell;
|
||||
use std::sync::Arc;
|
||||
use std::u32;
|
||||
use std::ops::Range;
|
||||
|
||||
use core::{self, DocContext};
|
||||
use doctree;
|
||||
@ -954,12 +955,20 @@ fn type_ns_kind(def: Def, path_str: &str) -> (&'static str, &'static str, String
|
||||
(kind, article, format!("{}@{}", kind, path_str))
|
||||
}
|
||||
|
||||
fn span_of_attrs(attrs: &Attributes) -> syntax_pos::Span {
|
||||
if attrs.doc_strings.is_empty() {
|
||||
return DUMMY_SP;
|
||||
}
|
||||
let start = attrs.doc_strings[0].span();
|
||||
let end = attrs.doc_strings.last().unwrap().span();
|
||||
start.to(end)
|
||||
}
|
||||
|
||||
fn ambiguity_error(cx: &DocContext, attrs: &Attributes,
|
||||
path_str: &str,
|
||||
article1: &str, kind1: &str, disambig1: &str,
|
||||
article2: &str, kind2: &str, disambig2: &str) {
|
||||
let sp = attrs.doc_strings.first()
|
||||
.map_or(DUMMY_SP, |a| a.span());
|
||||
let sp = span_of_attrs(attrs);
|
||||
cx.sess()
|
||||
.struct_span_warn(sp,
|
||||
&format!("`{}` is both {} {} and {} {}",
|
||||
@ -1174,8 +1183,39 @@ enum PathKind {
|
||||
Type,
|
||||
}
|
||||
|
||||
fn resolution_failure(cx: &DocContext, path_str: &str) {
|
||||
cx.sess().warn(&format!("[{}] cannot be resolved, ignoring it...", path_str));
|
||||
fn resolution_failure(
|
||||
cx: &DocContext,
|
||||
attrs: &Attributes,
|
||||
path_str: &str,
|
||||
dox: &str,
|
||||
link_range: Option<Range<usize>>,
|
||||
) {
|
||||
let sp = span_of_attrs(attrs);
|
||||
let mut diag = cx.sess()
|
||||
.struct_span_warn(sp, &format!("[{}] cannot be resolved, ignoring it...", path_str));
|
||||
|
||||
if let Some(link_range) = link_range {
|
||||
// blah blah blah\nblah\nblah [blah] blah blah\nblah blah
|
||||
// ^ ~~~~~~
|
||||
// | link_range
|
||||
// last_new_line_offset
|
||||
|
||||
let last_new_line_offset = dox[..link_range.start].rfind('\n').map_or(0, |n| n + 1);
|
||||
let line = dox[last_new_line_offset..].lines().next().unwrap_or("");
|
||||
|
||||
// Print the line containing the `link_range` and manually mark it with '^'s
|
||||
diag.note(&format!(
|
||||
"the link appears in this line:\n\n{line}\n{indicator: <before$}{indicator:^<found$}",
|
||||
line=line,
|
||||
indicator="",
|
||||
before=link_range.start - last_new_line_offset,
|
||||
found=link_range.len(),
|
||||
));
|
||||
} else {
|
||||
|
||||
}
|
||||
|
||||
diag.emit();
|
||||
}
|
||||
|
||||
impl Clean<Attributes> for [ast::Attribute] {
|
||||
@ -1184,7 +1224,7 @@ impl Clean<Attributes> for [ast::Attribute] {
|
||||
|
||||
if UnstableFeatures::from_environment().is_nightly_build() {
|
||||
let dox = attrs.collapsed_doc_value().unwrap_or_else(String::new);
|
||||
for ori_link in markdown_links(&dox) {
|
||||
for (ori_link, link_range) in markdown_links(&dox) {
|
||||
// bail early for real links
|
||||
if ori_link.contains('/') {
|
||||
continue;
|
||||
@ -1228,7 +1268,7 @@ impl Clean<Attributes> for [ast::Attribute] {
|
||||
if let Ok(def) = resolve(cx, path_str, true) {
|
||||
def
|
||||
} else {
|
||||
resolution_failure(cx, path_str);
|
||||
resolution_failure(cx, &attrs, path_str, &dox, link_range);
|
||||
// this could just be a normal link or a broken link
|
||||
// we could potentially check if something is
|
||||
// "intra-doc-link-like" and warn in that case
|
||||
@ -1239,7 +1279,7 @@ impl Clean<Attributes> for [ast::Attribute] {
|
||||
if let Ok(def) = resolve(cx, path_str, false) {
|
||||
def
|
||||
} else {
|
||||
resolution_failure(cx, path_str);
|
||||
resolution_failure(cx, &attrs, path_str, &dox, link_range);
|
||||
// this could just be a normal link
|
||||
continue;
|
||||
}
|
||||
@ -1284,7 +1324,7 @@ impl Clean<Attributes> for [ast::Attribute] {
|
||||
} else if let Ok(value_def) = resolve(cx, path_str, true) {
|
||||
value_def
|
||||
} else {
|
||||
resolution_failure(cx, path_str);
|
||||
resolution_failure(cx, &attrs, path_str, &dox, link_range);
|
||||
// this could just be a normal link
|
||||
continue;
|
||||
}
|
||||
@ -1293,7 +1333,7 @@ impl Clean<Attributes> for [ast::Attribute] {
|
||||
if let Some(def) = macro_resolve(cx, path_str) {
|
||||
(def, None)
|
||||
} else {
|
||||
resolution_failure(cx, path_str);
|
||||
resolution_failure(cx, &attrs, path_str, &dox, link_range);
|
||||
continue
|
||||
}
|
||||
}
|
||||
@ -3030,7 +3070,7 @@ impl Clean<Option<Visibility>> for hir::Visibility {
|
||||
Some(match *self {
|
||||
hir::Visibility::Public => Visibility::Public,
|
||||
hir::Visibility::Inherited => Visibility::Inherited,
|
||||
hir::Visibility::Crate => Visibility::Crate,
|
||||
hir::Visibility::Crate(_) => Visibility::Crate,
|
||||
hir::Visibility::Restricted { ref path, .. } => {
|
||||
let path = path.clean(cx);
|
||||
let did = register_def(cx, path.def);
|
||||
|
@ -32,6 +32,8 @@ use std::cell::RefCell;
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
use std::default::Default;
|
||||
use std::fmt::{self, Write};
|
||||
use std::borrow::Cow;
|
||||
use std::ops::Range;
|
||||
use std::str;
|
||||
use syntax::feature_gate::UnstableFeatures;
|
||||
use syntax::codemap::Span;
|
||||
@ -747,7 +749,7 @@ pub fn plain_summary_line(md: &str) -> String {
|
||||
s
|
||||
}
|
||||
|
||||
pub fn markdown_links(md: &str) -> Vec<String> {
|
||||
pub fn markdown_links(md: &str) -> Vec<(String, Option<Range<usize>>)> {
|
||||
if md.is_empty() {
|
||||
return vec![];
|
||||
}
|
||||
@ -760,8 +762,22 @@ pub fn markdown_links(md: &str) -> Vec<String> {
|
||||
let shortcut_links = RefCell::new(vec![]);
|
||||
|
||||
{
|
||||
let locate = |s: &str| unsafe {
|
||||
let s_start = s.as_ptr();
|
||||
let s_end = s_start.add(s.len());
|
||||
let md_start = md.as_ptr();
|
||||
let md_end = md_start.add(md.len());
|
||||
if md_start <= s_start && s_end <= md_end {
|
||||
let start = s_start.offset_from(md_start) as usize;
|
||||
let end = s_end.offset_from(md_start) as usize;
|
||||
Some(start..end)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
};
|
||||
|
||||
let push = |_: &str, s: &str| {
|
||||
shortcut_links.borrow_mut().push(s.to_owned());
|
||||
shortcut_links.borrow_mut().push((s.to_owned(), locate(s)));
|
||||
None
|
||||
};
|
||||
let p = Parser::new_with_broken_link_callback(md, opts,
|
||||
@ -772,7 +788,10 @@ pub fn markdown_links(md: &str) -> Vec<String> {
|
||||
for ev in iter {
|
||||
if let Event::Start(Tag::Link(dest, _)) = ev {
|
||||
debug!("found link: {}", dest);
|
||||
links.push(dest.into_owned());
|
||||
links.push(match dest {
|
||||
Cow::Borrowed(s) => (s.to_owned(), locate(s)),
|
||||
Cow::Owned(s) => (s, None),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3055,6 +3055,7 @@ fn render_assoc_item(w: &mut fmt::Formatter,
|
||||
} else {
|
||||
(0, true)
|
||||
};
|
||||
render_attributes(w, meth)?;
|
||||
write!(w, "{}{}{}{}fn <a href='{href}' class='fnname'>{name}</a>\
|
||||
{generics}{decl}{where_clause}",
|
||||
VisSpace(&meth.visibility),
|
||||
|
@ -2041,16 +2041,16 @@
|
||||
|
||||
autoCollapseAllImpls(getPageId());
|
||||
|
||||
function createToggleWrapper() {
|
||||
function createToggleWrapper(tog) {
|
||||
var span = document.createElement('span');
|
||||
span.className = 'toggle-label';
|
||||
span.style.display = 'none';
|
||||
span.innerHTML = ' Expand attributes';
|
||||
toggle.appendChild(span);
|
||||
tog.appendChild(span);
|
||||
|
||||
var wrapper = document.createElement('div');
|
||||
wrapper.className = 'toggle-wrapper toggle-attributes';
|
||||
wrapper.appendChild(toggle);
|
||||
wrapper.appendChild(tog);
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
@ -2078,13 +2078,11 @@
|
||||
});
|
||||
}
|
||||
|
||||
onEach(document.getElementById('main').getElementsByTagName('pre'), function(e) {
|
||||
onEach(e.getElementsByClassName('attributes'), function(i_e) {
|
||||
i_e.parentNode.insertBefore(createToggleWrapper(), i_e);
|
||||
if (getCurrentValue("rustdoc-item-attributes") !== "false") {
|
||||
collapseDocs(i_e.previousSibling.childNodes[0], "toggle");
|
||||
}
|
||||
});
|
||||
onEach(document.getElementById('main').getElementsByClassName('attributes'), function(i_e) {
|
||||
i_e.parentNode.insertBefore(createToggleWrapper(toggle.cloneNode(true)), i_e);
|
||||
if (getCurrentValue("rustdoc-item-attributes") !== "false") {
|
||||
collapseDocs(i_e.previousSibling.childNodes[0], "toggle");
|
||||
}
|
||||
});
|
||||
|
||||
onEach(document.getElementsByClassName('rust-example-rendered'), function(e) {
|
||||
|
@ -561,7 +561,8 @@ a {
|
||||
content: '\2002\00a7\2002';
|
||||
}
|
||||
|
||||
.docblock a:not(.srclink):hover, .docblock-short a:not(.srclink):hover, .stability a {
|
||||
.docblock a:not(.srclink):not(.test-arrow):hover,
|
||||
.docblock-short a:not(.srclink):not(.test-arrow):hover, .stability a {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
@ -771,7 +772,7 @@ h3 > .collapse-toggle, h4 > .collapse-toggle {
|
||||
|
||||
.toggle-wrapper {
|
||||
position: relative;
|
||||
margin-top: 5px;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.toggle-wrapper.collapsed {
|
||||
@ -854,10 +855,19 @@ span.since {
|
||||
|
||||
.attributes {
|
||||
display: block;
|
||||
margin: 0px 0px 0px 30px !important;
|
||||
margin-top: 0px !important;
|
||||
margin-right: 0px;
|
||||
margin-bottom: 0px !important;
|
||||
margin-left: 30px;
|
||||
}
|
||||
.toggle-attributes.collapsed {
|
||||
margin-bottom: 5px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.impl-items > .toggle-attributes {
|
||||
margin-left: 20px;
|
||||
}
|
||||
.impl-items .attributes {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
:target > code {
|
||||
|
@ -163,7 +163,8 @@ a {
|
||||
color: #ddd;
|
||||
}
|
||||
|
||||
.docblock a:not(.srclink), .docblock-short a:not(.srclink), .stability a {
|
||||
.docblock a:not(.srclink):not(.test-arrow), .docblock-short a:not(.srclink):not(.test-arrow),
|
||||
.stability a {
|
||||
color: #D2991D;
|
||||
}
|
||||
|
||||
|
@ -163,7 +163,8 @@ a {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.docblock a:not(.srclink), .docblock-short a:not(.srclink), .stability a {
|
||||
.docblock a:not(.srclink):not(.test-arrow), .docblock-short a:not(.srclink):not(.test-arrow),
|
||||
.stability a {
|
||||
color: #3873AD;
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
#![feature(test)]
|
||||
#![feature(vec_remove_item)]
|
||||
#![feature(entry_and_modify)]
|
||||
#![feature(ptr_offset_from)]
|
||||
|
||||
#![recursion_limit="256"]
|
||||
|
||||
|
@ -68,7 +68,8 @@ impl<'a, 'tcx, 'rcx> LibEmbargoVisitor<'a, 'tcx, 'rcx> {
|
||||
}
|
||||
|
||||
for item in self.cx.tcx.item_children(def_id).iter() {
|
||||
if !item.is_import || item.vis == Visibility::Public {
|
||||
if self.cx.tcx.def_key(item.def.def_id()).parent.map_or(false, |d| d == def_id.index) ||
|
||||
item.vis == Visibility::Public {
|
||||
self.visit_item(item.def);
|
||||
}
|
||||
}
|
||||
|
@ -2250,6 +2250,11 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
|
||||
|
||||
/// Gets a mutable reference to the value in the entry.
|
||||
///
|
||||
/// If you need a reference to the `OccupiedEntry` which may outlive the
|
||||
/// destruction of the `Entry` value, see [`into_mut`].
|
||||
///
|
||||
/// [`into_mut`]: #method.into_mut
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
@ -2261,10 +2266,14 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
|
||||
///
|
||||
/// assert_eq!(map["poneyland"], 12);
|
||||
/// if let Entry::Occupied(mut o) = map.entry("poneyland") {
|
||||
/// *o.get_mut() += 10;
|
||||
/// *o.get_mut() += 10;
|
||||
/// assert_eq!(*o.get(), 22);
|
||||
///
|
||||
/// // We can use the same Entry multiple times.
|
||||
/// *o.get_mut() += 2;
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(map["poneyland"], 22);
|
||||
/// assert_eq!(map["poneyland"], 24);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn get_mut(&mut self) -> &mut V {
|
||||
@ -2274,6 +2283,10 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
|
||||
/// Converts the OccupiedEntry into a mutable reference to the value in the entry
|
||||
/// with a lifetime bound to the map itself.
|
||||
///
|
||||
/// If you need multiple references to the `OccupiedEntry`, see [`get_mut`].
|
||||
///
|
||||
/// [`get_mut`]: #method.get_mut
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
|
@ -317,6 +317,8 @@
|
||||
#![cfg_attr(windows, feature(used))]
|
||||
#![feature(doc_alias)]
|
||||
#![feature(float_internals)]
|
||||
#![feature(panic_info_message)]
|
||||
#![cfg_attr(not(stage0), feature(panic_implementation))]
|
||||
|
||||
#![default_lib_allocator]
|
||||
|
||||
|
@ -319,8 +319,8 @@ pub fn panicking() -> bool {
|
||||
|
||||
/// Entry point of panic from the libcore crate.
|
||||
#[cfg(not(test))]
|
||||
#[cfg(stage0)]
|
||||
#[lang = "panic_fmt"]
|
||||
#[unwind(allowed)]
|
||||
pub extern fn rust_begin_panic(msg: fmt::Arguments,
|
||||
file: &'static str,
|
||||
line: u32,
|
||||
@ -328,59 +328,107 @@ pub extern fn rust_begin_panic(msg: fmt::Arguments,
|
||||
begin_panic_fmt(&msg, &(file, line, col))
|
||||
}
|
||||
|
||||
/// Entry point of panic from the libcore crate.
|
||||
#[cfg(not(test))]
|
||||
#[cfg(not(stage0))]
|
||||
#[panic_implementation]
|
||||
#[unwind(allowed)]
|
||||
pub fn rust_begin_panic(info: &PanicInfo) -> ! {
|
||||
continue_panic_fmt(&info)
|
||||
}
|
||||
|
||||
/// The entry point for panicking with a formatted message.
|
||||
///
|
||||
/// This is designed to reduce the amount of code required at the call
|
||||
/// site as much as possible (so that `panic!()` has as low an impact
|
||||
/// on (e.g.) the inlining of other functions as possible), by moving
|
||||
/// the actual formatting into this shared place.
|
||||
#[cfg(stage0)]
|
||||
#[unstable(feature = "libstd_sys_internals",
|
||||
reason = "used by the panic! macro",
|
||||
issue = "0")]
|
||||
#[inline(never)] #[cold]
|
||||
pub fn begin_panic_fmt(msg: &fmt::Arguments,
|
||||
file_line_col: &(&'static str, u32, u32)) -> ! {
|
||||
use fmt::Write;
|
||||
|
||||
// We do two allocations here, unfortunately. But (a) they're
|
||||
// required with the current scheme, and (b) we don't handle
|
||||
// panic + OOM properly anyway (see comment in begin_panic
|
||||
// below).
|
||||
|
||||
rust_panic_with_hook(&mut PanicPayload::new(msg), Some(msg), file_line_col);
|
||||
}
|
||||
|
||||
struct PanicPayload<'a> {
|
||||
inner: &'a fmt::Arguments<'a>,
|
||||
string: Option<String>,
|
||||
// NOTE(stage0) move into `continue_panic_fmt` on next stage0 update
|
||||
struct PanicPayload<'a> {
|
||||
inner: &'a fmt::Arguments<'a>,
|
||||
string: Option<String>,
|
||||
}
|
||||
|
||||
impl<'a> PanicPayload<'a> {
|
||||
fn new(inner: &'a fmt::Arguments<'a>) -> PanicPayload<'a> {
|
||||
PanicPayload { inner, string: None }
|
||||
}
|
||||
|
||||
impl<'a> PanicPayload<'a> {
|
||||
fn new(inner: &'a fmt::Arguments<'a>) -> PanicPayload<'a> {
|
||||
PanicPayload { inner, string: None }
|
||||
}
|
||||
fn fill(&mut self) -> &mut String {
|
||||
use fmt::Write;
|
||||
|
||||
fn fill(&mut self) -> &mut String {
|
||||
let inner = self.inner;
|
||||
self.string.get_or_insert_with(|| {
|
||||
let mut s = String::new();
|
||||
drop(s.write_fmt(*inner));
|
||||
s
|
||||
})
|
||||
}
|
||||
let inner = self.inner;
|
||||
self.string.get_or_insert_with(|| {
|
||||
let mut s = String::new();
|
||||
drop(s.write_fmt(*inner));
|
||||
s
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'a> BoxMeUp for PanicPayload<'a> {
|
||||
fn box_me_up(&mut self) -> *mut (Any + Send) {
|
||||
let contents = mem::replace(self.fill(), String::new());
|
||||
Box::into_raw(Box::new(contents))
|
||||
}
|
||||
|
||||
unsafe impl<'a> BoxMeUp for PanicPayload<'a> {
|
||||
fn box_me_up(&mut self) -> *mut (Any + Send) {
|
||||
let contents = mem::replace(self.fill(), String::new());
|
||||
Box::into_raw(Box::new(contents))
|
||||
}
|
||||
|
||||
fn get(&mut self) -> &(Any + Send) {
|
||||
self.fill()
|
||||
}
|
||||
fn get(&mut self) -> &(Any + Send) {
|
||||
self.fill()
|
||||
}
|
||||
}
|
||||
|
||||
/// The entry point for panicking with a formatted message.
|
||||
///
|
||||
/// This is designed to reduce the amount of code required at the call
|
||||
/// site as much as possible (so that `panic!()` has as low an impact
|
||||
/// on (e.g.) the inlining of other functions as possible), by moving
|
||||
/// the actual formatting into this shared place.
|
||||
#[cfg(not(stage0))]
|
||||
#[unstable(feature = "libstd_sys_internals",
|
||||
reason = "used by the panic! macro",
|
||||
issue = "0")]
|
||||
#[inline(never)] #[cold]
|
||||
pub fn begin_panic_fmt(msg: &fmt::Arguments,
|
||||
file_line_col: &(&'static str, u32, u32)) -> ! {
|
||||
let (file, line, col) = *file_line_col;
|
||||
let info = PanicInfo::internal_constructor(
|
||||
Some(msg),
|
||||
Location::internal_constructor(file, line, col),
|
||||
);
|
||||
continue_panic_fmt(&info)
|
||||
}
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
fn continue_panic_fmt(info: &PanicInfo) -> ! {
|
||||
// We do two allocations here, unfortunately. But (a) they're
|
||||
// required with the current scheme, and (b) we don't handle
|
||||
// panic + OOM properly anyway (see comment in begin_panic
|
||||
// below).
|
||||
|
||||
let loc = info.location().unwrap(); // The current implementation always returns Some
|
||||
let msg = info.message().unwrap(); // The current implementation always returns Some
|
||||
let file_line_col = (loc.file(), loc.line(), loc.column());
|
||||
rust_panic_with_hook(
|
||||
&mut PanicPayload::new(msg),
|
||||
info.message(),
|
||||
&file_line_col);
|
||||
}
|
||||
|
||||
/// This is the entry point of panicking for panic!() and assert!().
|
||||
#[unstable(feature = "libstd_sys_internals",
|
||||
reason = "used by the panic! macro",
|
||||
@ -431,7 +479,7 @@ pub fn begin_panic<M: Any + Send>(msg: M, file_line_col: &(&'static str, u32, u3
|
||||
/// abort or unwind.
|
||||
fn rust_panic_with_hook(payload: &mut BoxMeUp,
|
||||
message: Option<&fmt::Arguments>,
|
||||
file_line_col: &(&'static str, u32, u32)) -> ! {
|
||||
file_line_col: &(&str, u32, u32)) -> ! {
|
||||
let (file, line, col) = *file_line_col;
|
||||
|
||||
let panics = update_panic_count(1);
|
||||
|
@ -473,6 +473,8 @@ declare_features! (
|
||||
// 'a: { break 'a; }
|
||||
(active, label_break_value, "1.28.0", Some(48594), None),
|
||||
|
||||
// #[panic_implementation]
|
||||
(active, panic_implementation, "1.28.0", Some(44489), None),
|
||||
);
|
||||
|
||||
declare_features! (
|
||||
@ -1069,6 +1071,12 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG
|
||||
"attribute is currently unstable",
|
||||
cfg_fn!(wasm_custom_section))),
|
||||
|
||||
// RFC 2070
|
||||
("panic_implementation", Normal, Gated(Stability::Unstable,
|
||||
"panic_implementation",
|
||||
"#[panic_implementation] is an unstable feature",
|
||||
cfg_fn!(panic_implementation))),
|
||||
|
||||
// Crate level attributes
|
||||
("crate_name", CrateLevel, Ungated),
|
||||
("crate_type", CrateLevel, Ungated),
|
||||
|
22
src/test/compile-fail/auxiliary/some-panic-impl.rs
Normal file
22
src/test/compile-fail/auxiliary/some-panic-impl.rs
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
// no-prefer-dynamic
|
||||
|
||||
#![crate_type = "rlib"]
|
||||
#![feature(panic_implementation)]
|
||||
#![no_std]
|
||||
|
||||
use core::panic::PanicInfo;
|
||||
|
||||
#[panic_implementation]
|
||||
fn panic(info: &PanicInfo) -> ! {
|
||||
loop {}
|
||||
}
|
@ -14,9 +14,11 @@
|
||||
|
||||
#![feature(lang_items)]
|
||||
|
||||
#[lang = "panic_fmt"]
|
||||
fn panic_fmt() -> ! {
|
||||
//~^ ERROR: duplicate lang item found: `panic_fmt`.
|
||||
use std::panic::PanicInfo;
|
||||
|
||||
#[lang = "panic_impl"]
|
||||
fn panic_impl(info: &PanicInfo) -> ! {
|
||||
//~^ ERROR: duplicate lang item found: `panic_impl`.
|
||||
loop {}
|
||||
}
|
||||
|
||||
|
@ -12,8 +12,9 @@
|
||||
// compile-flags: --edition 2015
|
||||
// compile-pass
|
||||
|
||||
#![deny(rust_2018_idioms)]
|
||||
#![warn(rust_2018_idioms)]
|
||||
|
||||
extern crate edition_extern_crate_allowed;
|
||||
//~^ WARNING unused extern crate
|
||||
|
||||
fn main() {}
|
||||
|
21
src/test/compile-fail/feature-gate-panic-implementation.rs
Normal file
21
src/test/compile-fail/feature-gate-panic-implementation.rs
Normal file
@ -0,0 +1,21 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
// compile-flags:-C panic=abort
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use core::panic::PanicInfo;
|
||||
|
||||
#[panic_implementation] //~ ERROR #[panic_implementation] is an unstable feature (see issue #44489)
|
||||
fn panic(info: &PanicInfo) -> ! {
|
||||
loop {}
|
||||
}
|
@ -21,4 +21,4 @@ fn main() {
|
||||
|
||||
#[lang = "eh_personality"] extern fn eh_personality() {}
|
||||
#[lang = "eh_unwind_resume"] extern fn eh_unwind_resume() {}
|
||||
#[lang = "panic_fmt"] fn panic_fmt() -> ! { loop {} }
|
||||
#[lang = "panic_impl"] fn panic_impl() -> ! { loop {} }
|
||||
|
@ -0,0 +1,24 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
// compile-flags:-C panic=abort
|
||||
|
||||
#![feature(panic_implementation)]
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use core::panic::PanicInfo;
|
||||
|
||||
#[panic_implementation]
|
||||
fn panic(
|
||||
info: PanicInfo, //~ ERROR argument should be `&PanicInfo`
|
||||
) -> () //~ ERROR return type should be `!`
|
||||
{
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
// compile-flags:-C panic=abort
|
||||
|
||||
#![feature(panic_implementation)]
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use core::panic::PanicInfo;
|
||||
|
||||
#[panic_implementation]
|
||||
fn panic(
|
||||
info: &'static PanicInfo, //~ ERROR argument should be `&PanicInfo`
|
||||
) -> !
|
||||
{
|
||||
loop {}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
// compile-flags:-C panic=abort
|
||||
|
||||
#![feature(panic_implementation)]
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use core::panic::PanicInfo;
|
||||
|
||||
#[panic_implementation]
|
||||
fn panic() -> ! { //~ ERROR function should have one argument
|
||||
loop {}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
// compile-flags:-C panic=abort
|
||||
|
||||
#![feature(panic_implementation)]
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use core::panic::PanicInfo;
|
||||
|
||||
#[panic_implementation]
|
||||
fn panic<T>(pi: &PanicInfo) -> ! {
|
||||
//~^ ERROR `#[panic_implementation]` function should have no type parameters
|
||||
loop {}
|
||||
}
|
28
src/test/compile-fail/panic-implementation-duplicate.rs
Normal file
28
src/test/compile-fail/panic-implementation-duplicate.rs
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
// compile-flags:-C panic=abort
|
||||
|
||||
#![feature(lang_items)]
|
||||
#![feature(panic_implementation)]
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use core::panic::PanicInfo;
|
||||
|
||||
#[panic_implementation]
|
||||
fn panic(info: &PanicInfo) -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[lang = "panic_impl"]
|
||||
fn panic2(info: &PanicInfo) -> ! { //~ ERROR duplicate lang item found: `panic_impl`.
|
||||
loop {}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
// compile-flags:-C panic=abort
|
||||
// error-pattern: language item required, but not found: `panic_info`
|
||||
|
||||
#![feature(lang_items)]
|
||||
#![feature(no_core)]
|
||||
#![feature(panic_implementation)]
|
||||
#![no_core]
|
||||
#![no_main]
|
||||
|
||||
#[panic_implementation]
|
||||
fn panic() -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[lang = "sized"]
|
||||
trait Sized {}
|
22
src/test/compile-fail/panic-implementation-std.rs
Normal file
22
src/test/compile-fail/panic-implementation-std.rs
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
// error-pattern: duplicate lang item found: `panic_impl`.
|
||||
|
||||
#![feature(panic_implementation)]
|
||||
|
||||
use std::panic::PanicInfo;
|
||||
|
||||
#[panic_implementation]
|
||||
fn panic(info: PanicInfo) -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
fn main() {}
|
29
src/test/compile-fail/panic-implementation-twice.rs
Normal file
29
src/test/compile-fail/panic-implementation-twice.rs
Normal file
@ -0,0 +1,29 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
// aux-build:some-panic-impl.rs
|
||||
|
||||
#![feature(panic_implementation)]
|
||||
#![feature(lang_items)]
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
extern crate some_panic_impl;
|
||||
|
||||
use core::panic::PanicInfo;
|
||||
|
||||
#[panic_implementation]
|
||||
fn panic(info: &PanicInfo) -> ! {
|
||||
//~^ error duplicate lang item found: `panic_impl`
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[lang = "eh_personality"]
|
||||
fn eh() {}
|
@ -15,8 +15,10 @@
|
||||
#![no_std]
|
||||
#![feature(lang_items)]
|
||||
|
||||
#[lang = "panic_fmt"]
|
||||
fn panic_fmt() {}
|
||||
use core::panic::PanicInfo;
|
||||
|
||||
#[lang = "panic_impl"]
|
||||
fn panic_impl(info: &PanicInfo) -> ! { loop {} }
|
||||
#[lang = "eh_personality"]
|
||||
fn eh_personality() {}
|
||||
#[lang = "eh_unwind_resume"]
|
||||
|
@ -9,7 +9,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
// aux-build:weak-lang-items.rs
|
||||
// error-pattern: language item required, but not found: `panic_fmt`
|
||||
// error-pattern: language item required, but not found: `panic_impl`
|
||||
// error-pattern: language item required, but not found: `eh_personality`
|
||||
// ignore-wasm32-bare compiled with panic=abort, personality not required
|
||||
|
||||
|
21
src/test/run-make-fulldeps/issue-36710/Makefile
Normal file
21
src/test/run-make-fulldeps/issue-36710/Makefile
Normal file
@ -0,0 +1,21 @@
|
||||
-include ../tools.mk
|
||||
|
||||
ifeq (musl,$(findstring musl,$(TARGET)))
|
||||
all: skip
|
||||
else
|
||||
all: test
|
||||
endif
|
||||
|
||||
test: foo
|
||||
$(call RUN,foo)
|
||||
|
||||
skip:
|
||||
echo "expected failure"
|
||||
|
||||
foo: foo.rs $(call NATIVE_STATICLIB,foo)
|
||||
$(RUSTC) $< -lfoo $(EXTRACXXFLAGS)
|
||||
|
||||
$(TMPDIR)/libfoo.o: foo.cpp
|
||||
$(call COMPILE_OBJ_CXX,$@,$<)
|
||||
|
||||
.PHONY: all test skip
|
25
src/test/run-make-fulldeps/issue-36710/foo.cpp
Normal file
25
src/test/run-make-fulldeps/issue-36710/foo.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct A {
|
||||
A() { v = 1234; }
|
||||
~A() { v = 1; }
|
||||
uint32_t v;
|
||||
};
|
||||
|
||||
A a;
|
||||
|
||||
extern "C" {
|
||||
uint32_t get() {
|
||||
return a.v;
|
||||
}
|
||||
}
|
18
src/test/run-make-fulldeps/issue-36710/foo.rs
Normal file
18
src/test/run-make-fulldeps/issue-36710/foo.rs
Normal file
@ -0,0 +1,18 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
// Tests that linking to C++ code with global destructors works.
|
||||
|
||||
extern { fn get() -> u32; }
|
||||
|
||||
fn main() {
|
||||
let i = unsafe { get() };
|
||||
assert_eq!(i, 1234);
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
-include ../../run-make-fulldeps/tools.mk
|
||||
|
||||
# NOTE we use --emit=llvm-ir to avoid running the linker (linking will fail because there's no main
|
||||
# in this crate)
|
||||
all:
|
||||
$(RUSTC) panic-impl-provider.rs
|
||||
$(RUSTC) panic-impl-consumer.rs -C panic=abort --emit=llvm-ir -L $(TMPDIR)
|
@ -0,0 +1,15 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
// this crate provides the `panic_impl` lang item so we don't need to define it here
|
||||
extern crate panic_impl_provider;
|
@ -0,0 +1,20 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
#![crate_type = "rlib"]
|
||||
#![feature(panic_implementation)]
|
||||
#![no_std]
|
||||
|
||||
use core::panic::PanicInfo;
|
||||
|
||||
#[panic_implementation]
|
||||
fn panic(info: &PanicInfo) -> ! {
|
||||
loop {}
|
||||
}
|
@ -59,12 +59,14 @@ endif
|
||||
|
||||
ifdef IS_MSVC
|
||||
COMPILE_OBJ = $(CC) -c -Fo:`cygpath -w $(1)` $(2)
|
||||
COMPILE_OBJ_CXX = $(CXX) -c -Fo:`cygpath -w $(1)` $(2)
|
||||
NATIVE_STATICLIB_FILE = $(1).lib
|
||||
NATIVE_STATICLIB = $(TMPDIR)/$(call NATIVE_STATICLIB_FILE,$(1))
|
||||
OUT_EXE=-Fe:`cygpath -w $(TMPDIR)/$(call BIN,$(1))` \
|
||||
-Fo:`cygpath -w $(TMPDIR)/$(1).obj`
|
||||
else
|
||||
COMPILE_OBJ = $(CC) -c -o $(1) $(2)
|
||||
COMPILE_OBJ_CXX = $(CXX) -c -o $(1) $(2)
|
||||
NATIVE_STATICLIB_FILE = lib$(1).a
|
||||
NATIVE_STATICLIB = $(call STATICLIB,$(1))
|
||||
OUT_EXE=-o $(TMPDIR)/$(1)
|
||||
|
32
src/test/run-pass/const-endianess.rs
Normal file
32
src/test/run-pass/const-endianess.rs
Normal file
@ -0,0 +1,32 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
#![feature(const_int_ops)]
|
||||
#![feature(test)]
|
||||
|
||||
extern crate test;
|
||||
use test::black_box as b;
|
||||
|
||||
const BE_U32: u32 = 55u32.to_be();
|
||||
const LE_U32: u32 = 55u32.to_le();
|
||||
|
||||
|
||||
fn main() {
|
||||
assert_eq!(BE_U32, b(55u32).to_be());
|
||||
assert_eq!(LE_U32, b(55u32).to_le());
|
||||
|
||||
#[cfg(not(target_arch = "asmjs"))]
|
||||
{
|
||||
const BE_U128: u128 = 999999u128.to_be();
|
||||
const LE_I128: i128 = -999999i128.to_le();
|
||||
assert_eq!(BE_U128, b(999999u128).to_be());
|
||||
assert_eq!(LE_I128, b(-999999i128).to_le());
|
||||
}
|
||||
}
|
@ -10,7 +10,9 @@
|
||||
|
||||
// compile-pass
|
||||
|
||||
//! Test with [Foo::baz], [Bar::foo], [Uniooon::X]
|
||||
//! Test with [Foo::baz], [Bar::foo], ...
|
||||
//!
|
||||
//! and [Uniooon::X].
|
||||
|
||||
pub struct Foo {
|
||||
pub bar: usize,
|
||||
|
@ -1,6 +1,39 @@
|
||||
warning: [Foo::baz] cannot be resolved, ignoring it...
|
||||
--> $DIR/intra-links-warning.rs:13:1
|
||||
|
|
||||
13 | / //! Test with [Foo::baz], [Bar::foo], ...
|
||||
14 | | //!
|
||||
15 | | //! and [Uniooon::X].
|
||||
| |_____________________^
|
||||
|
|
||||
= note: the link appears in this line:
|
||||
|
||||
Test with [Foo::baz], [Bar::foo], ...
|
||||
^^^^^^^^
|
||||
|
||||
warning: [Bar::foo] cannot be resolved, ignoring it...
|
||||
--> $DIR/intra-links-warning.rs:13:1
|
||||
|
|
||||
13 | / //! Test with [Foo::baz], [Bar::foo], ...
|
||||
14 | | //!
|
||||
15 | | //! and [Uniooon::X].
|
||||
| |_____________________^
|
||||
|
|
||||
= note: the link appears in this line:
|
||||
|
||||
Test with [Foo::baz], [Bar::foo], ...
|
||||
^^^^^^^^
|
||||
|
||||
warning: [Uniooon::X] cannot be resolved, ignoring it...
|
||||
--> $DIR/intra-links-warning.rs:13:1
|
||||
|
|
||||
13 | / //! Test with [Foo::baz], [Bar::foo], ...
|
||||
14 | | //!
|
||||
15 | | //! and [Uniooon::X].
|
||||
| |_____________________^
|
||||
|
|
||||
= note: the link appears in this line:
|
||||
|
||||
and [Uniooon::X].
|
||||
^^^^^^^^^^
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
// no-prefer-dynamic
|
||||
// ignore-stage1
|
||||
|
||||
#![crate_type = "proc-macro"]
|
||||
|
||||
|
32
src/test/rustdoc/trait-attributes.rs
Normal file
32
src/test/rustdoc/trait-attributes.rs
Normal file
@ -0,0 +1,32 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
#![crate_name = "foo"]
|
||||
|
||||
// ignore-tidy-linelength
|
||||
|
||||
pub trait Foo {
|
||||
// @has foo/trait.Foo.html '//h3[@id="tymethod.foo"]//div[@class="docblock attributes"]' '#[must_use]'
|
||||
#[must_use]
|
||||
fn foo();
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub struct Bar;
|
||||
|
||||
impl Bar {
|
||||
// @has foo/struct.Bar.html '//h4[@id="method.bar"]//div[@class="docblock attributes"]' '#[must_use]'
|
||||
#[must_use]
|
||||
pub fn bar() {}
|
||||
|
||||
// @has foo/struct.Bar.html '//h4[@id="method.bar2"]//div[@class="docblock attributes"]' '#[must_use]'
|
||||
#[must_use]
|
||||
pub fn bar2() {}
|
||||
}
|
@ -10,48 +10,90 @@
|
||||
|
||||
// compile-flags: --edition 2018
|
||||
|
||||
#![deny(unnecessary_extern_crates)]
|
||||
#![deny(unused_extern_crates)]
|
||||
#![feature(alloc, test, libc)]
|
||||
|
||||
extern crate alloc;
|
||||
//~^ ERROR `extern crate` is unnecessary in the new edition
|
||||
//~^ ERROR unused extern crate
|
||||
//~| HELP remove
|
||||
extern crate alloc as x;
|
||||
//~^ ERROR `extern crate` is unnecessary in the new edition
|
||||
//~| HELP use `use`
|
||||
//~^ ERROR unused extern crate
|
||||
//~| HELP remove
|
||||
|
||||
#[macro_use]
|
||||
extern crate test;
|
||||
pub extern crate test as y;
|
||||
//~^ ERROR `extern crate` is unnecessary in the new edition
|
||||
//~| HELP use `pub use`
|
||||
pub extern crate libc;
|
||||
//~^ ERROR `extern crate` is unnecessary in the new edition
|
||||
//~| HELP use `pub use`
|
||||
|
||||
pub extern crate test as y;
|
||||
//~^ ERROR `extern crate` is not idiomatic in the new edition
|
||||
//~| HELP convert it to a `pub use`
|
||||
|
||||
pub extern crate libc;
|
||||
//~^ ERROR `extern crate` is not idiomatic in the new edition
|
||||
//~| HELP convert it to a `pub use`
|
||||
|
||||
pub(crate) extern crate libc as a;
|
||||
//~^ ERROR `extern crate` is not idiomatic in the new edition
|
||||
//~| HELP convert it to a `pub(crate) use`
|
||||
|
||||
crate extern crate libc as b;
|
||||
//~^ ERROR `extern crate` is not idiomatic in the new edition
|
||||
//~| HELP convert it to a `crate use`
|
||||
|
||||
mod foo {
|
||||
pub(in crate::foo) extern crate libc as c;
|
||||
//~^ ERROR `extern crate` is not idiomatic in the new edition
|
||||
//~| HELP convert it to a `pub(in crate::foo) use`
|
||||
|
||||
pub(super) extern crate libc as d;
|
||||
//~^ ERROR `extern crate` is not idiomatic in the new edition
|
||||
//~| HELP convert it to a `pub(super) use`
|
||||
|
||||
extern crate alloc;
|
||||
//~^ ERROR `extern crate` is unnecessary in the new edition
|
||||
//~| HELP use `use`
|
||||
//~^ ERROR unused extern crate
|
||||
//~| HELP remove
|
||||
|
||||
extern crate alloc as x;
|
||||
//~^ ERROR `extern crate` is unnecessary in the new edition
|
||||
//~| HELP use `use`
|
||||
//~^ ERROR unused extern crate
|
||||
//~| HELP remove
|
||||
|
||||
pub extern crate test;
|
||||
//~^ ERROR `extern crate` is unnecessary in the new edition
|
||||
//~| HELP use `pub use`
|
||||
//~^ ERROR `extern crate` is not idiomatic in the new edition
|
||||
//~| HELP convert it
|
||||
|
||||
pub extern crate test as y;
|
||||
//~^ ERROR `extern crate` is unnecessary in the new edition
|
||||
//~| HELP use `pub use`
|
||||
//~^ ERROR `extern crate` is not idiomatic in the new edition
|
||||
//~| HELP convert it
|
||||
|
||||
mod bar {
|
||||
extern crate alloc;
|
||||
//~^ ERROR `extern crate` is unnecessary in the new edition
|
||||
//~| HELP use `use`
|
||||
//~^ ERROR unused extern crate
|
||||
//~| HELP remove
|
||||
|
||||
extern crate alloc as x;
|
||||
//~^ ERROR `extern crate` is unnecessary in the new edition
|
||||
//~| HELP use `use`
|
||||
//~^ ERROR unused extern crate
|
||||
//~| HELP remove
|
||||
|
||||
pub(in crate::foo::bar) extern crate libc as e;
|
||||
//~^ ERROR `extern crate` is not idiomatic in the new edition
|
||||
//~| HELP convert it to a `pub(in crate::foo::bar) use`
|
||||
|
||||
fn dummy() {
|
||||
unsafe {
|
||||
e::getpid();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn dummy() {
|
||||
unsafe {
|
||||
c::getpid();
|
||||
d::getpid();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn main() {}
|
||||
fn main() {
|
||||
unsafe { a::getpid(); }
|
||||
unsafe { b::getpid(); }
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user