Merge branch 'master' into stabilise/termination-test

This commit is contained in:
Dylan DPC 2018-06-04 10:58:56 +05:30 committed by GitHub
commit 72f2f1935d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
118 changed files with 2173 additions and 565 deletions

View File

@ -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

View File

@ -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() {

View File

@ -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()):

View File

@ -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"),
},]

View File

@ -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")
}

View File

@ -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));

View File

@ -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);

View File

@ -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,

View File

@ -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);
}

View File

@ -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))

View File

@ -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");
}

View File

@ -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

View File

@ -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`

View File

@ -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

View File

@ -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
///
/// ```

View File

@ -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)]

View File

@ -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};

View File

@ -1326,6 +1326,7 @@ fn test_str_default() {
t::<&str>();
t::<String>();
t::<&mut str>();
}
#[test]

View File

@ -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]

View File

@ -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)]

View File

@ -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
///

View File

@ -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;

View File

@ -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;

View File

@ -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() }

View File

@ -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)
}
}

View File

@ -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) }
}

View File

@ -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
///

View File

@ -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> {}

View File

@ -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.
///

View File

@ -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.
///

View File

@ -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();
}
```

View File

@ -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 {

View File

@ -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 {

View File

@ -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));

View File

@ -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,
}
}

View File

@ -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<()> {

View File

@ -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>>

View File

@ -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;
}

View File

@ -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;

View File

@ -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.

View File

@ -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;

View File

@ -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],

View File

@ -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
}

View File

@ -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).
///

View File

@ -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.

View File

@ -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);
}

View File

@ -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();

View File

@ -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;

View File

@ -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:
//

View File

@ -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 });
}
_ => {}
}

View File

@ -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,

View File

@ -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

View File

@ -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);

View File

@ -1008,7 +1008,6 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
def: def,
span: binding.span,
vis: binding.vis,
is_import: true,
});
}
}

View File

@ -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;

View File

@ -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);

View File

@ -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) {

View File

@ -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)
}

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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),
});
}
}
}

View File

@ -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),

View File

@ -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 = '&nbsp;Expand&nbsp;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) {

View File

@ -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 {

View File

@ -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;
}

View File

@ -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;
}

View File

@ -23,6 +23,7 @@
#![feature(test)]
#![feature(vec_remove_item)]
#![feature(entry_and_modify)]
#![feature(ptr_offset_from)]
#![recursion_limit="256"]

View File

@ -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);
}
}

View File

@ -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
///
/// ```

View File

@ -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]

View File

@ -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);

View File

@ -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),

View 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 {}
}

View File

@ -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 {}
}

View File

@ -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() {}

View 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 {}
}

View File

@ -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 {} }

View File

@ -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 `!`
{
}

View 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.
// 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 {}
}

View 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.
// 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 {}
}

View File

@ -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 {}
}

View 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 {}
}

View File

@ -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 {}

View 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() {}

View 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() {}

View File

@ -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"]

View File

@ -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

View 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

View 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;
}
}

View 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);
}

View File

@ -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)

View File

@ -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;

View File

@ -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 {}
}

View File

@ -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)

View 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());
}
}

View File

@ -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,

View File

@ -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].
^^^^^^^^^^

View File

@ -9,6 +9,7 @@
// except according to those terms.
// no-prefer-dynamic
// ignore-stage1
#![crate_type = "proc-macro"]

View 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() {}
}

View File

@ -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