diff --git a/config.toml.example b/config.toml.example index 33ad9147ce0..5054a8f44b9 100644 --- a/config.toml.example +++ b/config.toml.example @@ -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 diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index 6f27402233f..4607ca5cf9f 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -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() { diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 487440becf6..28f5192f2cd 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -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()): diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 4fdb36b3f6e..9300b94156a 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -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"), },] diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index a516af58b1e..b3ccb3cc3c9 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -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) -> 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) -> 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) -> 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, backend: Interned) -> 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) -> PathBuf { - builder.cargo_out(compiler, Mode::Tool, target).join(".rustdoc-check.stamp") + builder.cargo_out(compiler, Mode::ToolRustc, target).join(".rustdoc-check.stamp") } diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 231ed9d40d2..11d9154ba69 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -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) -> 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) -> 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) -> 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, backend: Interned) -> 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)); diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 9840682d137..47feb8a8ab6 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -303,6 +303,7 @@ struct Rust { dist_src: Option, quiet_tests: Option, test_miri: Option, + incremental: Option, save_toolstates: Option, codegen_backends: Option>, codegen_backends_dir: Option, @@ -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); diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index e21a59390b7..7341137e20d 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -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, diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index cb229938521..19599b33ebe 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -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); } diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index f64161fb027..d16d7a52065 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -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)) diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 92847786792..a0b6222421d 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -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"); } diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 29f37b36e2a..d4a2e96cc0d 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -28,7 +28,7 @@ use toolstate::ToolState; pub struct CleanTools { pub compiler: Compiler, pub target: Interned, - 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, 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 = 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 diff --git a/src/doc/unstable-book/src/language-features/lang-items.md b/src/doc/unstable-book/src/language-features/lang-items.md index 6a7aea7f1c2..bac619fd4a3 100644 --- a/src/doc/unstable-book/src/language-features/lang-items.md +++ b/src/doc/unstable-book/src/language-features/lang-items.md @@ -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` diff --git a/src/doc/unstable-book/src/language-features/used.md b/src/doc/unstable-book/src/language-features/used.md index 75a8b2774f4..c3b7f2e41e1 100644 --- a/src/doc/unstable-book/src/language-features/used.md +++ b/src/doc/unstable-book/src/language-features/used.md @@ -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 diff --git a/src/liballoc/btree/map.rs b/src/liballoc/btree/map.rs index 28c42144b2a..9b6f91c039f 100644 --- a/src/liballoc/btree/map.rs +++ b/src/liballoc/btree/map.rs @@ -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 /// /// ``` diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 91de3ad0c39..a56420d52d0 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -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)] diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index 90bc2f9769c..c27c596e797 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -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}; diff --git a/src/liballoc/tests/str.rs b/src/liballoc/tests/str.rs index 03d295d16e6..75306ac82df 100644 --- a/src/liballoc/tests/str.rs +++ b/src/liballoc/tests/str.rs @@ -1326,6 +1326,7 @@ fn test_str_default() { t::<&str>(); t::(); + t::<&mut str>(); } #[test] diff --git a/src/libcore/alloc.rs b/src/libcore/alloc.rs index 6172a98bca6..229758803c8 100644 --- a/src/libcore/alloc.rs +++ b/src/libcore/alloc.rs @@ -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() -> (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() -> Self { let (size, align) = size_align::(); // 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: &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 { 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(n: usize) -> Result { Layout::new::() .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] diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 32cf31231c3..b27552651a0 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -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)] diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index c033b670798..9fed4990345 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -635,8 +635,9 @@ pub fn swap(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 /// diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index e5dbc65cd99..577c823f9a0 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -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; diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index eb769c4ad5a..b8e3dd6ed64 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -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; diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index ea652ad811e..26dd08b10b9 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -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() } diff --git a/src/libcore/panic.rs b/src/libcore/panic.rs index 27ec4aaac75..37ae05309af 100644 --- a/src/libcore/panic.rs +++ b/src/libcore/panic.rs @@ -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) } } diff --git a/src/libcore/panicking.rs b/src/libcore/panicking.rs index 6b3dc75af46..0d4f8d1141e 100644 --- a/src/libcore/panicking.rs +++ b/src/libcore/panicking.rs @@ -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) } +} diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 6c0709caa08..39315d8f0c8 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -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 /// diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index d52cc8cbe3f..c5792d62aa9 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -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 {} + #[stable(feature = "slice_get_slice", since = "1.28.0")] + impl Sealed for ops::RangeTo {} + #[stable(feature = "slice_get_slice", since = "1.28.0")] + impl Sealed for ops::RangeFrom {} + #[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 {} + #[stable(feature = "slice_get_slice", since = "1.28.0")] + impl Sealed for ops::RangeToInclusive {} +} + /// 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 { +pub trait SliceIndex: 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> {} diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 3169893fcde..5e1a9c25a21 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -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. /// diff --git a/src/libcore/time.rs b/src/libcore/time.rs index a1815b5f5ef..563eea0066d 100644 --- a/src/libcore/time.rs +++ b/src/libcore/time.rs @@ -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. /// diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 2662e709991..61f05ca3473 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -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(); } ``` diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs index ae1cf6046fb..0adbdbe9933 100644 --- a/src/librustc/hir/def.rs +++ b/src/librustc/hir/def.rs @@ -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 { diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index f816ba9ab81..1e48a54e018 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -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 { diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index 13df1ced603..7835d4e782c 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -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)); diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index ebc59964172..b7c66398f85 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -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, id: NodeId }, Inherited, } @@ -1964,7 +1964,7 @@ impl Visibility { match self { &Public | &Inherited => false, - &Crate | + &Crate(_) | &Restricted { .. } => true, } } diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 4bee4f9add0..2cf627fdc16 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -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<()> { diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index 9b202f55f3c..a781fc7240a 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -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> for hir::Visibility { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, @@ -758,10 +763,12 @@ impl<'a> HashStable> 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> diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index e3b20789714..7ebc0d4a4de 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -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; } diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index d70f994e87b..fe676919a7d 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -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; diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index f2120d97868..959dda69e30 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -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. diff --git a/src/librustc/middle/weak_lang_items.rs b/src/librustc/middle/weak_lang_items.rs index 42e4d3861ba..3c2ea047218 100644 --- a/src/librustc/middle/weak_lang_items.rs +++ b/src/librustc/middle/weak_lang_items.rs @@ -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; diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index cc8e8c7c31c..2c8f021c6a5 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -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 = (None, parse_opt_bool, [TRACKED], "enable ThinLTO when possible"), inline_in_all_cgus: Option = (None, parse_opt_bool, [TRACKED], diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index c6b1d94e597..82f351782bb 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -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 } diff --git a/src/librustc/traits/query/normalize.rs b/src/librustc/traits/query/normalize.rs index 1e9e9c056c9..f08b95f59fa 100644 --- a/src/librustc/traits/query/normalize.rs +++ b/src/librustc/traits/query/normalize.rs @@ -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). /// diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index f0f4adde7ee..0bb0208e2a1 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -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. diff --git a/src/librustc_codegen_llvm/back/link.rs b/src/librustc_codegen_llvm/back/link.rs index 735c4d2f76f..4e9910e58f3 100644 --- a/src/librustc_codegen_llvm/back/link.rs +++ b/src/librustc_codegen_llvm/back/link.rs @@ -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); } diff --git a/src/librustc_codegen_llvm/mir/block.rs b/src/librustc_codegen_llvm/mir/block.rs index 1669059a760..14d20b6dbe2 100644 --- a/src/librustc_codegen_llvm/mir/block.rs +++ b/src/librustc_codegen_llvm/mir/block.rs @@ -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(); diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 8a0850595c8..79c7a791147 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -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; diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index c5994d0536e..d6ce5b2ea57 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -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: // diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 69e873bb95d..fd00cde375b 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -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 }); } _ => {} } diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index fedd0774df4..4c282f037a5 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -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, diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs index 52ceb3ff595..74b9315f0c1 100644 --- a/src/librustc_passes/rvalue_promotion.rs +++ b/src/librustc_passes/rvalue_promotion.rs @@ -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 diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 0cc59e3129c..fe6909f7591 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -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); diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 34f84597adf..c44f330128a 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -1008,7 +1008,6 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { def: def, span: binding.span, vis: binding.vis, - is_import: true, }); } } diff --git a/src/librustc_target/spec/linux_musl_base.rs b/src/librustc_target/spec/linux_musl_base.rs index 293f23eab38..7a3f3c2a518 100644 --- a/src/librustc_target/spec/linux_musl_base.rs +++ b/src/librustc_target/spec/linux_musl_base.rs @@ -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; diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index a0cbfe2fefa..e54cd773123 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -426,12 +426,13 @@ pub struct TargetOptions { /// Linker to invoke pub linker: Option, - /// 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, // ... when linking an executable + pub pre_link_objects_exe: Vec, // ... when linking an executable, unconditionally + pub pre_link_objects_exe_crt: Vec, // ... when linking an executable with a bundled crt pub pre_link_objects_dll: Vec, // ... 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, + pub post_link_objects: Vec, // ... unconditionally + pub post_link_objects_crt: Vec, // ... 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); diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 6031984350b..86cd8d0fb2c 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -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) { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 90b974fb972..c2c71d90f06 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -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) } diff --git a/src/librustc_typeck/check_unused.rs b/src/librustc_typeck/check_unused.rs index bff849d7ae8..41adde0d4a1 100644 --- a/src/librustc_typeck/check_unused.rs +++ b/src/librustc_typeck/check_unused.rs @@ -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 = + 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, +} + +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, +} + +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); - } -} diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 2e3ea3de7b0..1c1ba208678 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -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>, +) { + 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: for [ast::Attribute] { @@ -1184,7 +1224,7 @@ impl Clean 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 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 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 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 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> 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); diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index c09bd4cc84a..7088104cd7a 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -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 { +pub fn markdown_links(md: &str) -> Vec<(String, Option>)> { if md.is_empty() { return vec![]; } @@ -760,8 +762,22 @@ pub fn markdown_links(md: &str) -> Vec { 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 { 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), + }); } } } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 109765b6711..5377cd9a391 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -3055,6 +3055,7 @@ fn render_assoc_item(w: &mut fmt::Formatter, } else { (0, true) }; + render_attributes(w, meth)?; write!(w, "{}{}{}{}fn {name}\ {generics}{decl}{where_clause}", VisSpace(&meth.visibility), diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index bb9a7e47232..0c937759120 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -2041,16 +2041,16 @@ autoCollapseAllImpls(getPageId()); - function createToggleWrapper() { + function createToggleWrapper(tog) { var span = document.createElement('span'); span.className = 'toggle-label'; span.style.display = 'none'; span.innerHTML = ' Expand attributes'; - toggle.appendChild(span); + tog.appendChild(span); var wrapper = document.createElement('div'); wrapper.className = 'toggle-wrapper toggle-attributes'; - wrapper.appendChild(toggle); + wrapper.appendChild(tog); return wrapper; } @@ -2078,13 +2078,11 @@ }); } - onEach(document.getElementById('main').getElementsByTagName('pre'), function(e) { - onEach(e.getElementsByClassName('attributes'), function(i_e) { - i_e.parentNode.insertBefore(createToggleWrapper(), i_e); - if (getCurrentValue("rustdoc-item-attributes") !== "false") { - collapseDocs(i_e.previousSibling.childNodes[0], "toggle"); - } - }); + onEach(document.getElementById('main').getElementsByClassName('attributes'), function(i_e) { + i_e.parentNode.insertBefore(createToggleWrapper(toggle.cloneNode(true)), i_e); + if (getCurrentValue("rustdoc-item-attributes") !== "false") { + collapseDocs(i_e.previousSibling.childNodes[0], "toggle"); + } }); onEach(document.getElementsByClassName('rust-example-rendered'), function(e) { diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 83abf35c854..773b8174e56 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -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 { diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css index 765ef0cd415..f96dcd9ec1c 100644 --- a/src/librustdoc/html/static/themes/dark.css +++ b/src/librustdoc/html/static/themes/dark.css @@ -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; } diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css index 5971dc43ded..54cf50cfffd 100644 --- a/src/librustdoc/html/static/themes/light.css +++ b/src/librustdoc/html/static/themes/light.css @@ -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; } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 1b713a446a0..97c84d8348f 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -23,6 +23,7 @@ #![feature(test)] #![feature(vec_remove_item)] #![feature(entry_and_modify)] +#![feature(ptr_offset_from)] #![recursion_limit="256"] diff --git a/src/librustdoc/visit_lib.rs b/src/librustdoc/visit_lib.rs index 15a8b58d0f6..4c773fc1dd7 100644 --- a/src/librustdoc/visit_lib.rs +++ b/src/librustdoc/visit_lib.rs @@ -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); } } diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 935ea4b62b5..5cbd8891364 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -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 /// /// ``` diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index f7d06852f27..c576245edb7 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -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] diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index 403056240bf..0808efa2ece 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -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, +// NOTE(stage0) move into `continue_panic_fmt` on next stage0 update +struct PanicPayload<'a> { + inner: &'a fmt::Arguments<'a>, + string: Option, +} + +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(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); diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 9adfb61d92d..17118e4dff2 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -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), diff --git a/src/test/compile-fail/auxiliary/some-panic-impl.rs b/src/test/compile-fail/auxiliary/some-panic-impl.rs new file mode 100644 index 00000000000..db16ac325ac --- /dev/null +++ b/src/test/compile-fail/auxiliary/some-panic-impl.rs @@ -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 or the MIT license +// , 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 {} +} diff --git a/src/test/compile-fail/duplicate_entry_error.rs b/src/test/compile-fail/duplicate_entry_error.rs index 485519e8c3d..176aa7cca53 100644 --- a/src/test/compile-fail/duplicate_entry_error.rs +++ b/src/test/compile-fail/duplicate_entry_error.rs @@ -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 {} } diff --git a/src/test/compile-fail/edition-extern-crate-allowed.rs b/src/test/compile-fail/edition-extern-crate-allowed.rs index 286ee896161..7368564e250 100644 --- a/src/test/compile-fail/edition-extern-crate-allowed.rs +++ b/src/test/compile-fail/edition-extern-crate-allowed.rs @@ -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() {} diff --git a/src/test/compile-fail/feature-gate-panic-implementation.rs b/src/test/compile-fail/feature-gate-panic-implementation.rs new file mode 100644 index 00000000000..ae9fbc7b13b --- /dev/null +++ b/src/test/compile-fail/feature-gate-panic-implementation.rs @@ -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 or the MIT license +// , 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 {} +} diff --git a/src/test/compile-fail/no_owned_box_lang_item.rs b/src/test/compile-fail/no_owned_box_lang_item.rs index 72eb687adc6..1c2bf1573dc 100644 --- a/src/test/compile-fail/no_owned_box_lang_item.rs +++ b/src/test/compile-fail/no_owned_box_lang_item.rs @@ -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 {} } diff --git a/src/test/compile-fail/panic-implementation-bad-signature-1.rs b/src/test/compile-fail/panic-implementation-bad-signature-1.rs new file mode 100644 index 00000000000..fec11fdbd7b --- /dev/null +++ b/src/test/compile-fail/panic-implementation-bad-signature-1.rs @@ -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 or the MIT license +// , 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 `!` +{ +} diff --git a/src/test/compile-fail/panic-implementation-bad-signature-2.rs b/src/test/compile-fail/panic-implementation-bad-signature-2.rs new file mode 100644 index 00000000000..2a628c05699 --- /dev/null +++ b/src/test/compile-fail/panic-implementation-bad-signature-2.rs @@ -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 or the MIT license +// , 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 {} +} diff --git a/src/test/compile-fail/panic-implementation-bad-signature-3.rs b/src/test/compile-fail/panic-implementation-bad-signature-3.rs new file mode 100644 index 00000000000..29337025b70 --- /dev/null +++ b/src/test/compile-fail/panic-implementation-bad-signature-3.rs @@ -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 or the MIT license +// , 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 {} +} diff --git a/src/test/compile-fail/panic-implementation-bad-signature-4.rs b/src/test/compile-fail/panic-implementation-bad-signature-4.rs new file mode 100644 index 00000000000..d5f942ba2d6 --- /dev/null +++ b/src/test/compile-fail/panic-implementation-bad-signature-4.rs @@ -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 or the MIT license +// , 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(pi: &PanicInfo) -> ! { + //~^ ERROR `#[panic_implementation]` function should have no type parameters + loop {} +} diff --git a/src/test/compile-fail/panic-implementation-duplicate.rs b/src/test/compile-fail/panic-implementation-duplicate.rs new file mode 100644 index 00000000000..017113af409 --- /dev/null +++ b/src/test/compile-fail/panic-implementation-duplicate.rs @@ -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 or the MIT license +// , 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 {} +} diff --git a/src/test/compile-fail/panic-implementation-requires-panic-info.rs b/src/test/compile-fail/panic-implementation-requires-panic-info.rs new file mode 100644 index 00000000000..597f44d9832 --- /dev/null +++ b/src/test/compile-fail/panic-implementation-requires-panic-info.rs @@ -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 or the MIT license +// , 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 {} diff --git a/src/test/compile-fail/panic-implementation-std.rs b/src/test/compile-fail/panic-implementation-std.rs new file mode 100644 index 00000000000..f25cd3605c1 --- /dev/null +++ b/src/test/compile-fail/panic-implementation-std.rs @@ -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 or the MIT license +// , 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() {} diff --git a/src/test/compile-fail/panic-implementation-twice.rs b/src/test/compile-fail/panic-implementation-twice.rs new file mode 100644 index 00000000000..78dc545c036 --- /dev/null +++ b/src/test/compile-fail/panic-implementation-twice.rs @@ -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 or the MIT license +// , 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() {} diff --git a/src/test/compile-fail/panic-runtime/auxiliary/panic-runtime-lang-items.rs b/src/test/compile-fail/panic-runtime/auxiliary/panic-runtime-lang-items.rs index fbf70b3d3fe..d9848a554ab 100644 --- a/src/test/compile-fail/panic-runtime/auxiliary/panic-runtime-lang-items.rs +++ b/src/test/compile-fail/panic-runtime/auxiliary/panic-runtime-lang-items.rs @@ -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"] diff --git a/src/test/compile-fail/weak-lang-item.rs b/src/test/compile-fail/weak-lang-item.rs index 8579611b938..7b988c3595f 100644 --- a/src/test/compile-fail/weak-lang-item.rs +++ b/src/test/compile-fail/weak-lang-item.rs @@ -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 diff --git a/src/test/run-make-fulldeps/issue-36710/Makefile b/src/test/run-make-fulldeps/issue-36710/Makefile new file mode 100644 index 00000000000..928bdf532df --- /dev/null +++ b/src/test/run-make-fulldeps/issue-36710/Makefile @@ -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 diff --git a/src/test/run-make-fulldeps/issue-36710/foo.cpp b/src/test/run-make-fulldeps/issue-36710/foo.cpp new file mode 100644 index 00000000000..fbd0ead7a50 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-36710/foo.cpp @@ -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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#include + +struct A { + A() { v = 1234; } + ~A() { v = 1; } + uint32_t v; +}; + +A a; + +extern "C" { + uint32_t get() { + return a.v; + } +} diff --git a/src/test/run-make-fulldeps/issue-36710/foo.rs b/src/test/run-make-fulldeps/issue-36710/foo.rs new file mode 100644 index 00000000000..6e50566ddfd --- /dev/null +++ b/src/test/run-make-fulldeps/issue-36710/foo.rs @@ -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 or the MIT license +// , 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); +} diff --git a/src/test/run-make-fulldeps/panic-impl-transitive/Makefile b/src/test/run-make-fulldeps/panic-impl-transitive/Makefile new file mode 100644 index 00000000000..1714578b2ba --- /dev/null +++ b/src/test/run-make-fulldeps/panic-impl-transitive/Makefile @@ -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) diff --git a/src/test/run-make-fulldeps/panic-impl-transitive/panic-impl-consumer.rs b/src/test/run-make-fulldeps/panic-impl-transitive/panic-impl-consumer.rs new file mode 100644 index 00000000000..592fab8be85 --- /dev/null +++ b/src/test/run-make-fulldeps/panic-impl-transitive/panic-impl-consumer.rs @@ -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 or the MIT license +// , 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; diff --git a/src/test/run-make-fulldeps/panic-impl-transitive/panic-impl-provider.rs b/src/test/run-make-fulldeps/panic-impl-transitive/panic-impl-provider.rs new file mode 100644 index 00000000000..46cdf2e2fa5 --- /dev/null +++ b/src/test/run-make-fulldeps/panic-impl-transitive/panic-impl-provider.rs @@ -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 or the MIT license +// , 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 {} +} diff --git a/src/test/run-make-fulldeps/tools.mk b/src/test/run-make-fulldeps/tools.mk index af1707de6c0..3de358fa500 100644 --- a/src/test/run-make-fulldeps/tools.mk +++ b/src/test/run-make-fulldeps/tools.mk @@ -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) diff --git a/src/test/run-pass/const-endianess.rs b/src/test/run-pass/const-endianess.rs new file mode 100644 index 00000000000..fa34b49210a --- /dev/null +++ b/src/test/run-pass/const-endianess.rs @@ -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 or the MIT license +// , 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()); + } +} diff --git a/src/test/rustdoc-ui/intra-links-warning.rs b/src/test/rustdoc-ui/intra-links-warning.rs index 2a00d31e3d7..830aaabf9d2 100644 --- a/src/test/rustdoc-ui/intra-links-warning.rs +++ b/src/test/rustdoc-ui/intra-links-warning.rs @@ -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, diff --git a/src/test/rustdoc-ui/intra-links-warning.stderr b/src/test/rustdoc-ui/intra-links-warning.stderr index 67d7bdd02b3..1e8e9f04c26 100644 --- a/src/test/rustdoc-ui/intra-links-warning.stderr +++ b/src/test/rustdoc-ui/intra-links-warning.stderr @@ -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]. + ^^^^^^^^^^ diff --git a/src/test/rustdoc/rustc-macro-crate.rs b/src/test/rustdoc/rustc-macro-crate.rs index dc28732b55e..d46f9684411 100644 --- a/src/test/rustdoc/rustc-macro-crate.rs +++ b/src/test/rustdoc/rustc-macro-crate.rs @@ -9,6 +9,7 @@ // except according to those terms. // no-prefer-dynamic +// ignore-stage1 #![crate_type = "proc-macro"] diff --git a/src/test/rustdoc/trait-attributes.rs b/src/test/rustdoc/trait-attributes.rs new file mode 100644 index 00000000000..00d10408b4c --- /dev/null +++ b/src/test/rustdoc/trait-attributes.rs @@ -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 or the MIT license +// , 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() {} +} diff --git a/src/test/ui-fulldeps/unnecessary-extern-crate.rs b/src/test/ui-fulldeps/unnecessary-extern-crate.rs index fc6cb6bd053..0811c79b0a4 100644 --- a/src/test/ui-fulldeps/unnecessary-extern-crate.rs +++ b/src/test/ui-fulldeps/unnecessary-extern-crate.rs @@ -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(); } +} diff --git a/src/test/ui-fulldeps/unnecessary-extern-crate.stderr b/src/test/ui-fulldeps/unnecessary-extern-crate.stderr index b9ccf5b19e0..a4307112157 100644 --- a/src/test/ui-fulldeps/unnecessary-extern-crate.stderr +++ b/src/test/ui-fulldeps/unnecessary-extern-crate.stderr @@ -1,4 +1,4 @@ -error: `extern crate` is unnecessary in the new edition +error: unused extern crate --> $DIR/unnecessary-extern-crate.rs:16:1 | LL | extern crate alloc; @@ -7,62 +7,92 @@ LL | extern crate alloc; note: lint level defined here --> $DIR/unnecessary-extern-crate.rs:13:9 | -LL | #![deny(unnecessary_extern_crates)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #![deny(unused_extern_crates)] + | ^^^^^^^^^^^^^^^^^^^^ -error: `extern crate` is unnecessary in the new edition +error: unused extern crate --> $DIR/unnecessary-extern-crate.rs:19:1 | LL | extern crate alloc as x; - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use `use`: `use alloc as x;` + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it -error: `extern crate` is unnecessary in the new edition - --> $DIR/unnecessary-extern-crate.rs:25:1 +error: `extern crate` is not idiomatic in the new edition + --> $DIR/unnecessary-extern-crate.rs:26:1 | LL | pub extern crate test as y; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `pub use`: `pub use test as y;` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `pub use` -error: `extern crate` is unnecessary in the new edition - --> $DIR/unnecessary-extern-crate.rs:28:1 +error: `extern crate` is not idiomatic in the new edition + --> $DIR/unnecessary-extern-crate.rs:30:1 | LL | pub extern crate libc; - | ^^^^^^^^^^^^^^^^^^^^^^ help: use `pub use`: `pub use libc;` + | ^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `pub use` -error: `extern crate` is unnecessary in the new edition - --> $DIR/unnecessary-extern-crate.rs:34:5 +error: `extern crate` is not idiomatic in the new edition + --> $DIR/unnecessary-extern-crate.rs:34:1 | -LL | extern crate alloc; - | ^^^^^^^^^^^^^^^^^^^ help: use `use`: `use alloc;` +LL | pub(crate) extern crate libc as a; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `pub(crate) use` -error: `extern crate` is unnecessary in the new edition - --> $DIR/unnecessary-extern-crate.rs:37:5 +error: `extern crate` is not idiomatic in the new edition + --> $DIR/unnecessary-extern-crate.rs:38:1 | -LL | extern crate alloc as x; - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use `use`: `use alloc as x;` +LL | crate extern crate libc as b; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `crate use` -error: `extern crate` is unnecessary in the new edition - --> $DIR/unnecessary-extern-crate.rs:40:5 - | -LL | pub extern crate test; - | ^^^^^^^^^^^^^^^^^^^^^^ help: use `pub use`: `pub use test;` - -error: `extern crate` is unnecessary in the new edition +error: `extern crate` is not idiomatic in the new edition --> $DIR/unnecessary-extern-crate.rs:43:5 | -LL | pub extern crate test as y; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `pub use`: `pub use test as y;` +LL | pub(in crate::foo) extern crate libc as c; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `pub(in crate::foo) use` -error: `extern crate` is unnecessary in the new edition - --> $DIR/unnecessary-extern-crate.rs:47:9 +error: `extern crate` is not idiomatic in the new edition + --> $DIR/unnecessary-extern-crate.rs:47:5 + | +LL | pub(super) extern crate libc as d; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `pub(super) use` + +error: unused extern crate + --> $DIR/unnecessary-extern-crate.rs:51:5 + | +LL | extern crate alloc; + | ^^^^^^^^^^^^^^^^^^^ help: remove it + +error: unused extern crate + --> $DIR/unnecessary-extern-crate.rs:55:5 + | +LL | extern crate alloc as x; + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it + +error: `extern crate` is not idiomatic in the new edition + --> $DIR/unnecessary-extern-crate.rs:59:5 + | +LL | pub extern crate test; + | ^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `pub use` + +error: `extern crate` is not idiomatic in the new edition + --> $DIR/unnecessary-extern-crate.rs:63:5 + | +LL | pub extern crate test as y; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `pub use` + +error: unused extern crate + --> $DIR/unnecessary-extern-crate.rs:68:9 | LL | extern crate alloc; - | ^^^^^^^^^^^^^^^^^^^ help: use `use`: `use alloc;` + | ^^^^^^^^^^^^^^^^^^^ help: remove it -error: `extern crate` is unnecessary in the new edition - --> $DIR/unnecessary-extern-crate.rs:50:9 +error: unused extern crate + --> $DIR/unnecessary-extern-crate.rs:72:9 | LL | extern crate alloc as x; - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use `use`: `use alloc as x;` + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it -error: aborting due to 10 previous errors +error: `extern crate` is not idiomatic in the new edition + --> $DIR/unnecessary-extern-crate.rs:76:9 + | +LL | pub(in crate::foo::bar) extern crate libc as e; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `pub(in crate::foo::bar) use` + +error: aborting due to 15 previous errors diff --git a/src/test/ui/borrowck/promote-ref-mut-in-let-issue-46557.nll.stderr b/src/test/ui/borrowck/promote-ref-mut-in-let-issue-46557.nll.stderr new file mode 100644 index 00000000000..95acdab3e80 --- /dev/null +++ b/src/test/ui/borrowck/promote-ref-mut-in-let-issue-46557.nll.stderr @@ -0,0 +1,63 @@ +error[E0597]: borrowed value does not live long enough + --> $DIR/promote-ref-mut-in-let-issue-46557.rs:15:21 + | +LL | fn gimme_static_mut_let() -> &'static mut u32 { + | _______________________________________________- +LL | | let ref mut x = 1234543; //~ ERROR + | | ^^^^^^^ temporary value does not live long enough +LL | | x +LL | | } + | | - + | | | + | |_temporary value only lives until here + | borrow later used here + +error[E0597]: borrowed value does not live long enough + --> $DIR/promote-ref-mut-in-let-issue-46557.rs:20:25 + | +LL | fn gimme_static_mut_let_nested() -> &'static mut u32 { + | ______________________________________________________- +LL | | let (ref mut x, ) = (1234543, ); //~ ERROR + | | ^^^^^^^^^^^ temporary value does not live long enough +LL | | x +LL | | } + | | - + | | | + | |_temporary value only lives until here + | borrow later used here + +error[E0597]: borrowed value does not live long enough + --> $DIR/promote-ref-mut-in-let-issue-46557.rs:25:11 + | +LL | match 1234543 { + | ^^^^^^^ temporary value does not live long enough +... +LL | } + | - temporary value only lives until here + | + = note: borrowed value must be valid for the static lifetime... + +error[E0597]: borrowed value does not live long enough + --> $DIR/promote-ref-mut-in-let-issue-46557.rs:31:11 + | +LL | match (123443,) { + | ^^^^^^^^^ temporary value does not live long enough +... +LL | } + | - temporary value only lives until here + | + = note: borrowed value must be valid for the static lifetime... + +error[E0597]: borrowed value does not live long enough + --> $DIR/promote-ref-mut-in-let-issue-46557.rs:37:10 + | +LL | &mut 1234543 //~ ERROR + | ^^^^^^^ temporary value does not live long enough +LL | } + | - temporary value only lives until here + | + = note: borrowed value must be valid for the static lifetime... + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/borrowck/promote-ref-mut-in-let-issue-46557.rs b/src/test/ui/borrowck/promote-ref-mut-in-let-issue-46557.rs new file mode 100644 index 00000000000..4c5f458d6a3 --- /dev/null +++ b/src/test/ui/borrowck/promote-ref-mut-in-let-issue-46557.rs @@ -0,0 +1,41 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that we fail to promote the constant here which has a `ref +// mut` borrow. + +fn gimme_static_mut_let() -> &'static mut u32 { + let ref mut x = 1234543; //~ ERROR + x +} + +fn gimme_static_mut_let_nested() -> &'static mut u32 { + let (ref mut x, ) = (1234543, ); //~ ERROR + x +} + +fn gimme_static_mut_match() -> &'static mut u32 { + match 1234543 { + ref mut x => x //~ ERROR + } +} + +fn gimme_static_mut_match_nested() -> &'static mut u32 { + match (123443,) { + (ref mut x,) => x, //~ ERROR + } +} + +fn gimme_static_mut_ampersand() -> &'static mut u32 { + &mut 1234543 //~ ERROR +} + +fn main() { +} diff --git a/src/test/ui/borrowck/promote-ref-mut-in-let-issue-46557.stderr b/src/test/ui/borrowck/promote-ref-mut-in-let-issue-46557.stderr new file mode 100644 index 00000000000..931eb7da744 --- /dev/null +++ b/src/test/ui/borrowck/promote-ref-mut-in-let-issue-46557.stderr @@ -0,0 +1,57 @@ +error[E0597]: borrowed value does not live long enough + --> $DIR/promote-ref-mut-in-let-issue-46557.rs:15:9 + | +LL | let ref mut x = 1234543; //~ ERROR + | ^^^^^^^^^ temporary value does not live long enough +LL | x +LL | } + | - temporary value only lives until here + | + = note: borrowed value must be valid for the static lifetime... + +error[E0597]: borrowed value does not live long enough + --> $DIR/promote-ref-mut-in-let-issue-46557.rs:20:10 + | +LL | let (ref mut x, ) = (1234543, ); //~ ERROR + | ^^^^^^^^^ borrowed value does not live long enough +LL | x +LL | } + | - borrowed value only lives until here + | + = note: borrowed value must be valid for the static lifetime... + +error[E0597]: borrowed value does not live long enough + --> $DIR/promote-ref-mut-in-let-issue-46557.rs:26:9 + | +LL | ref mut x => x //~ ERROR + | ^^^^^^^^^ temporary value does not live long enough +LL | } +LL | } + | - temporary value only lives until here + | + = note: borrowed value must be valid for the static lifetime... + +error[E0597]: borrowed value does not live long enough + --> $DIR/promote-ref-mut-in-let-issue-46557.rs:32:10 + | +LL | (ref mut x,) => x, //~ ERROR + | ^^^^^^^^^ borrowed value does not live long enough +LL | } +LL | } + | - borrowed value only lives until here + | + = note: borrowed value must be valid for the static lifetime... + +error[E0597]: borrowed value does not live long enough + --> $DIR/promote-ref-mut-in-let-issue-46557.rs:37:10 + | +LL | &mut 1234543 //~ ERROR + | ^^^^^^^ temporary value does not live long enough +LL | } + | - temporary value only lives until here + | + = note: borrowed value must be valid for the static lifetime... + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/deriving-with-repr-packed.rs b/src/test/ui/deriving-with-repr-packed.rs index 0c52829799e..43375098cb5 100644 --- a/src/test/ui/deriving-with-repr-packed.rs +++ b/src/test/ui/deriving-with-repr-packed.rs @@ -33,7 +33,7 @@ pub struct Bar(u32, u32, u32); struct Y(usize); #[derive(PartialEq)] -//~^ ERROR #[derive] can't be used on a non-Copy #[repr(packed)] +//~^ ERROR #[derive] can't be used //~| hard error #[repr(packed)] struct X(Y); diff --git a/src/test/ui/deriving-with-repr-packed.stderr b/src/test/ui/deriving-with-repr-packed.stderr index 64aefbcd5df..a7599c1e7db 100644 --- a/src/test/ui/deriving-with-repr-packed.stderr +++ b/src/test/ui/deriving-with-repr-packed.stderr @@ -21,7 +21,7 @@ LL | #[derive(Copy, Clone, PartialEq, Eq)] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #46043 -error: #[derive] can't be used on a non-Copy #[repr(packed)] struct (error E0133) +error: #[derive] can't be used on a #[repr(packed)] struct that does not derive Copy (error E0133) --> $DIR/deriving-with-repr-packed.rs:26:10 | LL | #[derive(PartialEq, Eq)] @@ -30,7 +30,7 @@ LL | #[derive(PartialEq, Eq)] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #46043 -error: #[derive] can't be used on a non-Copy #[repr(packed)] struct (error E0133) +error: #[derive] can't be used on a #[repr(packed)] struct that does not derive Copy (error E0133) --> $DIR/deriving-with-repr-packed.rs:35:10 | LL | #[derive(PartialEq)] diff --git a/src/test/ui/error-codes/E0152.rs b/src/test/ui/error-codes/E0152.rs index ae501b94e3f..8fbad7b3ff3 100644 --- a/src/test/ui/error-codes/E0152.rs +++ b/src/test/ui/error-codes/E0152.rs @@ -10,7 +10,7 @@ #![feature(lang_items)] -#[lang = "panic_fmt"] +#[lang = "panic_impl"] struct Foo; //~ ERROR E0152 fn main() { diff --git a/src/test/ui/error-codes/E0152.stderr b/src/test/ui/error-codes/E0152.stderr index f67022bd6d3..c7f5f362efb 100644 --- a/src/test/ui/error-codes/E0152.stderr +++ b/src/test/ui/error-codes/E0152.stderr @@ -1,4 +1,4 @@ -error[E0152]: duplicate lang item found: `panic_fmt`. +error[E0152]: duplicate lang item found: `panic_impl`. --> $DIR/E0152.rs:14:1 | LL | struct Foo; //~ ERROR E0152 diff --git a/src/test/ui/issue-23217.stderr b/src/test/ui/issue-23217.stderr index d542a10e9b6..d87f239bca6 100644 --- a/src/test/ui/issue-23217.stderr +++ b/src/test/ui/issue-23217.stderr @@ -6,7 +6,7 @@ LL | pub enum SomeEnum { LL | B = SomeEnum::A, | ^^^^^^^^^^^ variant not found in `SomeEnum` | - = note: did you mean `variant::B`? + = note: did you mean `SomeEnum::B`? error: aborting due to previous error diff --git a/src/test/ui/issue-28971.stderr b/src/test/ui/issue-28971.stderr index df114351ff5..c04e21f7c58 100644 --- a/src/test/ui/issue-28971.stderr +++ b/src/test/ui/issue-28971.stderr @@ -7,7 +7,7 @@ LL | enum Foo { LL | Foo::Baz(..) => (), | ^^^^^^^^^^^^ variant not found in `Foo` | - = note: did you mean `variant::Bar`? + = note: did you mean `Foo::Bar`? error: aborting due to previous error diff --git a/src/test/ui/rfc-2166-underscore-imports/basic.stderr b/src/test/ui/rfc-2166-underscore-imports/basic.stderr index 4530d0fa604..c12c74b50e2 100644 --- a/src/test/ui/rfc-2166-underscore-imports/basic.stderr +++ b/src/test/ui/rfc-2166-underscore-imports/basic.stderr @@ -20,7 +20,7 @@ warning: unused extern crate --> $DIR/basic.rs:33:5 | LL | extern crate core as _; //~ WARN unused extern crate - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^ help: remove it | note: lint level defined here --> $DIR/basic.rs:14:25 diff --git a/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.fixed b/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.fixed new file mode 100644 index 00000000000..4f99c1240f8 --- /dev/null +++ b/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.fixed @@ -0,0 +1,36 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:edition-lint-paths.rs +// run-rustfix +// compile-flags:--edition 2018 + +// The "normal case". Ideally we would remove the `extern crate` here, +// but we don't. + +#![feature(rust_2018_preview)] +#![deny(rust_2018_idioms)] +#![allow(dead_code)] + + +//~^ ERROR unused extern crate + +use edition_lint_paths as bar; +//~^ ERROR `extern crate` is not idiomatic in the new edition + +fn main() { + // This is not considered to *use* the `extern crate` in Rust 2018: + use edition_lint_paths::foo; + foo(); + + // But this should be a use of the (renamed) crate: + crate::bar::foo(); +} + diff --git a/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.rs b/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.rs new file mode 100644 index 00000000000..9c1235a2967 --- /dev/null +++ b/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.rs @@ -0,0 +1,36 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:edition-lint-paths.rs +// run-rustfix +// compile-flags:--edition 2018 + +// The "normal case". Ideally we would remove the `extern crate` here, +// but we don't. + +#![feature(rust_2018_preview)] +#![deny(rust_2018_idioms)] +#![allow(dead_code)] + +extern crate edition_lint_paths; +//~^ ERROR unused extern crate + +extern crate edition_lint_paths as bar; +//~^ ERROR `extern crate` is not idiomatic in the new edition + +fn main() { + // This is not considered to *use* the `extern crate` in Rust 2018: + use edition_lint_paths::foo; + foo(); + + // But this should be a use of the (renamed) crate: + crate::bar::foo(); +} + diff --git a/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.stderr b/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.stderr new file mode 100644 index 00000000000..b3afa2bd1d5 --- /dev/null +++ b/src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.stderr @@ -0,0 +1,21 @@ +error: unused extern crate + --> $DIR/extern-crate-idiomatic-in-2018.rs:22:1 + | +LL | extern crate edition_lint_paths; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it + | +note: lint level defined here + --> $DIR/extern-crate-idiomatic-in-2018.rs:19:9 + | +LL | #![deny(rust_2018_idioms)] + | ^^^^^^^^^^^^^^^^ + = note: #[deny(unused_extern_crates)] implied by #[deny(rust_2018_idioms)] + +error: `extern crate` is not idiomatic in the new edition + --> $DIR/extern-crate-idiomatic-in-2018.rs:25:1 + | +LL | extern crate edition_lint_paths as bar; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `use` + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/suggestions/removing-extern-crate.fixed b/src/test/ui/suggestions/removing-extern-crate.fixed index 723137f5db0..83b35cec809 100644 --- a/src/test/ui/suggestions/removing-extern-crate.fixed +++ b/src/test/ui/suggestions/removing-extern-crate.fixed @@ -16,12 +16,12 @@ #![warn(rust_2018_idioms)] #![allow(unused_imports)] -use std as foo; + mod another { - use std as foo; - use std; + + } fn main() {} diff --git a/src/test/ui/suggestions/removing-extern-crate.stderr b/src/test/ui/suggestions/removing-extern-crate.stderr index 39d22de0277..f2eed27a266 100644 --- a/src/test/ui/suggestions/removing-extern-crate.stderr +++ b/src/test/ui/suggestions/removing-extern-crate.stderr @@ -1,31 +1,31 @@ -warning: `extern crate` is unnecessary in the new edition +warning: unused extern crate --> $DIR/removing-extern-crate.rs:19:1 | LL | extern crate std as foo; - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use `use`: `use std as foo;` + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it | note: lint level defined here --> $DIR/removing-extern-crate.rs:16:9 | LL | #![warn(rust_2018_idioms)] | ^^^^^^^^^^^^^^^^ - = note: #[warn(unnecessary_extern_crates)] implied by #[warn(rust_2018_idioms)] + = note: #[warn(unused_extern_crates)] implied by #[warn(rust_2018_idioms)] -warning: `extern crate` is unnecessary in the new edition +warning: unused extern crate --> $DIR/removing-extern-crate.rs:20:1 | LL | extern crate core; | ^^^^^^^^^^^^^^^^^^ help: remove it -warning: `extern crate` is unnecessary in the new edition +warning: unused extern crate --> $DIR/removing-extern-crate.rs:23:5 | LL | extern crate std as foo; - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use `use`: `use std as foo;` + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it -warning: `extern crate` is unnecessary in the new edition +warning: unused extern crate --> $DIR/removing-extern-crate.rs:24:5 | LL | extern crate std; - | ^^^^^^^^^^^^^^^^^ help: use `use`: `use std;` + | ^^^^^^^^^^^^^^^^^ help: remove it diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 5daf192e2db..cc00f200171 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2529,7 +2529,7 @@ impl<'test> TestCx<'test> { .env("IS_WINDOWS", "1") .env("MSVC_LIB", format!("'{}' -nologo", lib.display())) .env("CC", format!("'{}' {}", self.config.cc, cflags)) - .env("CXX", &self.config.cxx); + .env("CXX", format!("'{}'", &self.config.cxx)); } else { cmd.env("CC", format!("{} {}", self.config.cc, self.config.cflags)) .env("CXX", format!("{} {}", self.config.cxx, self.config.cflags)) diff --git a/src/tools/miri b/src/tools/miri index 066a284557f..e1734470e78 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit 066a284557ff6e6a2aa19084f599f167a724af7b +Subproject commit e1734470e780e05a3366a2f74cfa25ea88a518a5