From fb4095df94bf07dc745a0c0e07adc93b52f04673 Mon Sep 17 00:00:00 2001 From: Michael Hewson Date: Sat, 26 Oct 2019 16:44:06 -0400 Subject: [PATCH 01/19] Update comments re type parameter hack in object safety To check if a method's receiver type is object safe, we create a new receiver type by substituting in a bogus type parameter (let's call it `U`) for `Self`, and checking that the unmodified receiver type implements `DispatchFromDyn`. It would be better to use `dyn Trait` directly, and the only reason we don't is because it triggers another check that `Trait` is object safe, resulting in a query cycle. Once the feature `object_safe_for_dispatch` (tracking issue https://github.com/rust-lang/rust/issues/43561) is stabilized, this will no longer be the case, and we'll be able to use `dyn Trait` as the unsized `Self` type. I've updated the comments in object_safety.rs accordingly. --- src/librustc/traits/object_safety.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index e42c3a63541cc..8ded1417ee570 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -520,9 +520,11 @@ impl<'tcx> TyCtxt<'tcx> { /// a pointer. /// /// In practice, we cannot use `dyn Trait` explicitly in the obligation because it would result - /// in a new check that `Trait` is object safe, creating a cycle. So instead, we fudge a little - /// by introducing a new type parameter `U` such that `Self: Unsize` and `U: Trait + ?Sized`, - /// and use `U` in place of `dyn Trait`. Written as a chalk-style query: + /// in a new check that `Trait` is object safe, creating a cycle (until object_safe_for_dispatch + /// is stabilized, see tracking issue https://github.com/rust-lang/rust/issues/43561). + /// Instead, we fudge a little by introducing a new type parameter `U` such that + /// `Self: Unsize` and `U: Trait + ?Sized`, and use `U` in place of `dyn Trait`. + /// Written as a chalk-style query: /// /// forall (U: Trait + ?Sized) { /// if (Self: Unsize) { @@ -556,8 +558,8 @@ impl<'tcx> TyCtxt<'tcx> { // the type `U` in the query // use a bogus type parameter to mimick a forall(U) query using u32::MAX for now. - // FIXME(mikeyhew) this is a total hack, and we should replace it when real forall queries - // are implemented + // FIXME(mikeyhew) this is a total hack. Once object_safe_for_dispatch is stabilized, we can + // replace this with `dyn Trait` let unsized_self_ty: Ty<'tcx> = self.mk_ty_param( ::std::u32::MAX, Symbol::intern("RustaceansAreAwesome"), From e216b65883256eb01542b58ea69b9a610e0f88ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Sun, 6 Oct 2019 00:00:00 +0000 Subject: [PATCH 02/19] Remove sanitizer runtime crates --- Cargo.lock | 48 -------------- src/bootstrap/dist.rs | 4 -- src/build_helper/lib.rs | 119 ----------------------------------- src/librustc_asan/Cargo.toml | 20 ------ src/librustc_asan/build.rs | 30 --------- src/librustc_asan/lib.rs | 8 --- src/librustc_lsan/Cargo.toml | 20 ------ src/librustc_lsan/build.rs | 29 --------- src/librustc_lsan/lib.rs | 8 --- src/librustc_msan/Cargo.toml | 20 ------ src/librustc_msan/build.rs | 29 --------- src/librustc_msan/lib.rs | 8 --- src/librustc_tsan/Cargo.toml | 20 ------ src/librustc_tsan/build.rs | 30 --------- src/librustc_tsan/lib.rs | 8 --- src/libstd/Cargo.toml | 10 --- 16 files changed, 411 deletions(-) delete mode 100644 src/librustc_asan/Cargo.toml delete mode 100644 src/librustc_asan/build.rs delete mode 100644 src/librustc_asan/lib.rs delete mode 100644 src/librustc_lsan/Cargo.toml delete mode 100644 src/librustc_lsan/build.rs delete mode 100644 src/librustc_lsan/lib.rs delete mode 100644 src/librustc_msan/Cargo.toml delete mode 100644 src/librustc_msan/build.rs delete mode 100644 src/librustc_msan/lib.rs delete mode 100644 src/librustc_tsan/Cargo.toml delete mode 100644 src/librustc_tsan/build.rs delete mode 100644 src/librustc_tsan/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 64f3a7ac619c2..a228aaef0adb1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3411,17 +3411,6 @@ dependencies = [ "smallvec", ] -[[package]] -name = "rustc_asan" -version = "0.0.0" -dependencies = [ - "alloc", - "build_helper", - "cmake", - "compiler_builtins", - "core", -] - [[package]] name = "rustc_codegen_llvm" version = "0.0.0" @@ -3620,17 +3609,6 @@ dependencies = [ "cc", ] -[[package]] -name = "rustc_lsan" -version = "0.0.0" -dependencies = [ - "alloc", - "build_helper", - "cmake", - "compiler_builtins", - "core", -] - [[package]] name = "rustc_macros" version = "0.1.0" @@ -3685,17 +3663,6 @@ dependencies = [ "syntax_pos", ] -[[package]] -name = "rustc_msan" -version = "0.0.0" -dependencies = [ - "alloc", - "build_helper", - "cmake", - "compiler_builtins", - "core", -] - [[package]] name = "rustc_passes" version = "0.0.0" @@ -3810,17 +3777,6 @@ dependencies = [ "syntax_pos", ] -[[package]] -name = "rustc_tsan" -version = "0.0.0" -dependencies = [ - "alloc", - "build_helper", - "cmake", - "compiler_builtins", - "core", -] - [[package]] name = "rustc_typeck" version = "0.0.0" @@ -4176,10 +4132,6 @@ dependencies = [ "panic_unwind", "profiler_builtins", "rand 0.7.0", - "rustc_asan", - "rustc_lsan", - "rustc_msan", - "rustc_tsan", "unwind", "wasi", ] diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 93143570b0fe1..30ef8725d790a 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -960,10 +960,6 @@ impl Step for Src { "src/libcore", "src/libpanic_abort", "src/libpanic_unwind", - "src/librustc_asan", - "src/librustc_lsan", - "src/librustc_msan", - "src/librustc_tsan", "src/libstd", "src/libunwind", "src/libtest", diff --git a/src/build_helper/lib.rs b/src/build_helper/lib.rs index bb94fb2b755f5..9ada68ec5b7c2 100644 --- a/src/build_helper/lib.rs +++ b/src/build_helper/lib.rs @@ -1,9 +1,7 @@ -use std::fs::File; use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; use std::time::{SystemTime, UNIX_EPOCH}; use std::{env, fs}; -use std::thread; /// A helper macro to `unwrap` a result except also print out details like: /// @@ -189,123 +187,6 @@ pub fn up_to_date(src: &Path, dst: &Path) -> bool { } } -#[must_use] -pub struct NativeLibBoilerplate { - pub src_dir: PathBuf, - pub out_dir: PathBuf, -} - -impl NativeLibBoilerplate { - /// On macOS we don't want to ship the exact filename that compiler-rt builds. - /// This conflicts with the system and ours is likely a wildly different - /// version, so they can't be substituted. - /// - /// As a result, we rename it here but we need to also use - /// `install_name_tool` on macOS to rename the commands listed inside of it to - /// ensure it's linked against correctly. - pub fn fixup_sanitizer_lib_name(&self, sanitizer_name: &str) { - if env::var("TARGET").unwrap() != "x86_64-apple-darwin" { - return - } - - let dir = self.out_dir.join("build/lib/darwin"); - let name = format!("clang_rt.{}_osx_dynamic", sanitizer_name); - let src = dir.join(&format!("lib{}.dylib", name)); - let new_name = format!("lib__rustc__{}.dylib", name); - let dst = dir.join(&new_name); - - println!("{} => {}", src.display(), dst.display()); - fs::rename(&src, &dst).unwrap(); - let status = Command::new("install_name_tool") - .arg("-id") - .arg(format!("@rpath/{}", new_name)) - .arg(&dst) - .status() - .expect("failed to execute `install_name_tool`"); - assert!(status.success()); - } -} - -impl Drop for NativeLibBoilerplate { - fn drop(&mut self) { - if !thread::panicking() { - t!(File::create(self.out_dir.join("rustbuild.timestamp"))); - } - } -} - -// Perform standard preparations for native libraries that are build only once for all stages. -// Emit rerun-if-changed and linking attributes for Cargo, check if any source files are -// updated, calculate paths used later in actual build with CMake/make or C/C++ compiler. -// If Err is returned, then everything is up-to-date and further build actions can be skipped. -// Timestamps are created automatically when the result of `native_lib_boilerplate` goes out -// of scope, so all the build actions should be completed until then. -pub fn native_lib_boilerplate( - src_dir: &Path, - out_name: &str, - link_name: &str, - search_subdir: &str, -) -> Result { - rerun_if_changed_anything_in_dir(src_dir); - - let out_dir = env::var_os("RUSTBUILD_NATIVE_DIR").unwrap_or_else(|| - env::var_os("OUT_DIR").unwrap()); - let out_dir = PathBuf::from(out_dir).join(out_name); - t!(fs::create_dir_all(&out_dir)); - if link_name.contains('=') { - println!("cargo:rustc-link-lib={}", link_name); - } else { - println!("cargo:rustc-link-lib=static={}", link_name); - } - println!( - "cargo:rustc-link-search=native={}", - out_dir.join(search_subdir).display() - ); - - let timestamp = out_dir.join("rustbuild.timestamp"); - if !up_to_date(Path::new("build.rs"), ×tamp) || !up_to_date(src_dir, ×tamp) { - Ok(NativeLibBoilerplate { - src_dir: src_dir.to_path_buf(), - out_dir, - }) - } else { - Err(()) - } -} - -pub fn sanitizer_lib_boilerplate(sanitizer_name: &str) - -> Result<(NativeLibBoilerplate, String), ()> -{ - let (link_name, search_path, apple) = match &*env::var("TARGET").unwrap() { - "x86_64-unknown-linux-gnu" => ( - format!("clang_rt.{}-x86_64", sanitizer_name), - "build/lib/linux", - false, - ), - "x86_64-apple-darwin" => ( - format!("clang_rt.{}_osx_dynamic", sanitizer_name), - "build/lib/darwin", - true, - ), - _ => return Err(()), - }; - let to_link = if apple { - format!("dylib=__rustc__{}", link_name) - } else { - format!("static={}", link_name) - }; - // This env var is provided by rustbuild to tell us where `compiler-rt` - // lives. - let dir = env::var_os("RUST_COMPILER_RT_ROOT").unwrap(); - let lib = native_lib_boilerplate( - dir.as_ref(), - sanitizer_name, - &to_link, - search_path, - )?; - Ok((lib, link_name)) -} - fn dir_up_to_date(src: &Path, threshold: SystemTime) -> bool { t!(fs::read_dir(src)).map(|e| t!(e)).all(|e| { let meta = t!(e.metadata()); diff --git a/src/librustc_asan/Cargo.toml b/src/librustc_asan/Cargo.toml deleted file mode 100644 index df117de8720e0..0000000000000 --- a/src/librustc_asan/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -authors = ["The Rust Project Developers"] -build = "build.rs" -name = "rustc_asan" -version = "0.0.0" -edition = "2018" - -[lib] -name = "rustc_asan" -path = "lib.rs" -test = false - -[build-dependencies] -build_helper = { path = "../build_helper" } -cmake = "0.1.38" - -[dependencies] -alloc = { path = "../liballoc" } -core = { path = "../libcore" } -compiler_builtins = "0.1.0" diff --git a/src/librustc_asan/build.rs b/src/librustc_asan/build.rs deleted file mode 100644 index 645707ccc0338..0000000000000 --- a/src/librustc_asan/build.rs +++ /dev/null @@ -1,30 +0,0 @@ -use std::env; -use build_helper::sanitizer_lib_boilerplate; - -use cmake::Config; - -fn main() { - println!("cargo:rerun-if-env-changed=RUSTC_BUILD_SANITIZERS"); - if env::var("RUSTC_BUILD_SANITIZERS") != Ok("1".to_string()) { - return; - } - if let Some(llvm_config) = env::var_os("LLVM_CONFIG") { - build_helper::restore_library_path(); - - let (native, target) = match sanitizer_lib_boilerplate("asan") { - Ok(native) => native, - _ => return, - }; - - Config::new(&native.src_dir) - .define("COMPILER_RT_BUILD_SANITIZERS", "ON") - .define("COMPILER_RT_BUILD_BUILTINS", "OFF") - .define("COMPILER_RT_BUILD_XRAY", "OFF") - .define("LLVM_CONFIG_PATH", llvm_config) - .out_dir(&native.out_dir) - .build_target(&target) - .build(); - native.fixup_sanitizer_lib_name("asan"); - } - println!("cargo:rerun-if-env-changed=LLVM_CONFIG"); -} diff --git a/src/librustc_asan/lib.rs b/src/librustc_asan/lib.rs deleted file mode 100644 index d6c8e54c18db7..0000000000000 --- a/src/librustc_asan/lib.rs +++ /dev/null @@ -1,8 +0,0 @@ -#![sanitizer_runtime] -#![feature(nll)] -#![feature(sanitizer_runtime)] -#![feature(staged_api)] -#![no_std] -#![unstable(feature = "sanitizer_runtime_lib", - reason = "internal implementation detail of sanitizers", - issue = "0")] diff --git a/src/librustc_lsan/Cargo.toml b/src/librustc_lsan/Cargo.toml deleted file mode 100644 index 9a24361f44e64..0000000000000 --- a/src/librustc_lsan/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -authors = ["The Rust Project Developers"] -build = "build.rs" -name = "rustc_lsan" -version = "0.0.0" -edition = "2018" - -[lib] -name = "rustc_lsan" -path = "lib.rs" -test = false - -[build-dependencies] -build_helper = { path = "../build_helper" } -cmake = "0.1.38" - -[dependencies] -alloc = { path = "../liballoc" } -core = { path = "../libcore" } -compiler_builtins = "0.1.0" diff --git a/src/librustc_lsan/build.rs b/src/librustc_lsan/build.rs deleted file mode 100644 index 73720d8c2d64e..0000000000000 --- a/src/librustc_lsan/build.rs +++ /dev/null @@ -1,29 +0,0 @@ -use std::env; -use build_helper::sanitizer_lib_boilerplate; - -use cmake::Config; - -fn main() { - println!("cargo:rerun-if-env-changed=RUSTC_BUILD_SANITIZERS"); - if env::var("RUSTC_BUILD_SANITIZERS") != Ok("1".to_string()) { - return; - } - if let Some(llvm_config) = env::var_os("LLVM_CONFIG") { - build_helper::restore_library_path(); - - let (native, target) = match sanitizer_lib_boilerplate("lsan") { - Ok(native) => native, - _ => return, - }; - - Config::new(&native.src_dir) - .define("COMPILER_RT_BUILD_SANITIZERS", "ON") - .define("COMPILER_RT_BUILD_BUILTINS", "OFF") - .define("COMPILER_RT_BUILD_XRAY", "OFF") - .define("LLVM_CONFIG_PATH", llvm_config) - .out_dir(&native.out_dir) - .build_target(&target) - .build(); - } - println!("cargo:rerun-if-env-changed=LLVM_CONFIG"); -} diff --git a/src/librustc_lsan/lib.rs b/src/librustc_lsan/lib.rs deleted file mode 100644 index d6c8e54c18db7..0000000000000 --- a/src/librustc_lsan/lib.rs +++ /dev/null @@ -1,8 +0,0 @@ -#![sanitizer_runtime] -#![feature(nll)] -#![feature(sanitizer_runtime)] -#![feature(staged_api)] -#![no_std] -#![unstable(feature = "sanitizer_runtime_lib", - reason = "internal implementation detail of sanitizers", - issue = "0")] diff --git a/src/librustc_msan/Cargo.toml b/src/librustc_msan/Cargo.toml deleted file mode 100644 index bda4078572501..0000000000000 --- a/src/librustc_msan/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -authors = ["The Rust Project Developers"] -build = "build.rs" -name = "rustc_msan" -version = "0.0.0" -edition = "2018" - -[lib] -name = "rustc_msan" -path = "lib.rs" -test = false - -[build-dependencies] -build_helper = { path = "../build_helper" } -cmake = "0.1.38" - -[dependencies] -alloc = { path = "../liballoc" } -core = { path = "../libcore" } -compiler_builtins = "0.1.0" diff --git a/src/librustc_msan/build.rs b/src/librustc_msan/build.rs deleted file mode 100644 index a81786ee36d04..0000000000000 --- a/src/librustc_msan/build.rs +++ /dev/null @@ -1,29 +0,0 @@ -use std::env; -use build_helper::sanitizer_lib_boilerplate; - -use cmake::Config; - -fn main() { - println!("cargo:rerun-if-env-changed=RUSTC_BUILD_SANITIZERS"); - if env::var("RUSTC_BUILD_SANITIZERS") != Ok("1".to_string()) { - return; - } - if let Some(llvm_config) = env::var_os("LLVM_CONFIG") { - build_helper::restore_library_path(); - - let (native, target) = match sanitizer_lib_boilerplate("msan") { - Ok(native) => native, - _ => return, - }; - - Config::new(&native.src_dir) - .define("COMPILER_RT_BUILD_SANITIZERS", "ON") - .define("COMPILER_RT_BUILD_BUILTINS", "OFF") - .define("COMPILER_RT_BUILD_XRAY", "OFF") - .define("LLVM_CONFIG_PATH", llvm_config) - .out_dir(&native.out_dir) - .build_target(&target) - .build(); - } - println!("cargo:rerun-if-env-changed=LLVM_CONFIG"); -} diff --git a/src/librustc_msan/lib.rs b/src/librustc_msan/lib.rs deleted file mode 100644 index d6c8e54c18db7..0000000000000 --- a/src/librustc_msan/lib.rs +++ /dev/null @@ -1,8 +0,0 @@ -#![sanitizer_runtime] -#![feature(nll)] -#![feature(sanitizer_runtime)] -#![feature(staged_api)] -#![no_std] -#![unstable(feature = "sanitizer_runtime_lib", - reason = "internal implementation detail of sanitizers", - issue = "0")] diff --git a/src/librustc_tsan/Cargo.toml b/src/librustc_tsan/Cargo.toml deleted file mode 100644 index 82045dd0cddc7..0000000000000 --- a/src/librustc_tsan/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -authors = ["The Rust Project Developers"] -build = "build.rs" -name = "rustc_tsan" -version = "0.0.0" -edition = "2018" - -[lib] -name = "rustc_tsan" -path = "lib.rs" -test = false - -[build-dependencies] -build_helper = { path = "../build_helper" } -cmake = "0.1.38" - -[dependencies] -alloc = { path = "../liballoc" } -core = { path = "../libcore" } -compiler_builtins = "0.1.0" diff --git a/src/librustc_tsan/build.rs b/src/librustc_tsan/build.rs deleted file mode 100644 index f9333e1502327..0000000000000 --- a/src/librustc_tsan/build.rs +++ /dev/null @@ -1,30 +0,0 @@ -use std::env; -use build_helper::sanitizer_lib_boilerplate; - -use cmake::Config; - -fn main() { - println!("cargo:rerun-if-env-changed=RUSTC_BUILD_SANITIZERS"); - if env::var("RUSTC_BUILD_SANITIZERS") != Ok("1".to_string()) { - return; - } - if let Some(llvm_config) = env::var_os("LLVM_CONFIG") { - build_helper::restore_library_path(); - - let (native, target) = match sanitizer_lib_boilerplate("tsan") { - Ok(native) => native, - _ => return, - }; - - Config::new(&native.src_dir) - .define("COMPILER_RT_BUILD_SANITIZERS", "ON") - .define("COMPILER_RT_BUILD_BUILTINS", "OFF") - .define("COMPILER_RT_BUILD_XRAY", "OFF") - .define("LLVM_CONFIG_PATH", llvm_config) - .out_dir(&native.out_dir) - .build_target(&target) - .build(); - native.fixup_sanitizer_lib_name("tsan"); - } - println!("cargo:rerun-if-env-changed=LLVM_CONFIG"); -} diff --git a/src/librustc_tsan/lib.rs b/src/librustc_tsan/lib.rs deleted file mode 100644 index d6c8e54c18db7..0000000000000 --- a/src/librustc_tsan/lib.rs +++ /dev/null @@ -1,8 +0,0 @@ -#![sanitizer_runtime] -#![feature(nll)] -#![feature(sanitizer_runtime)] -#![feature(staged_api)] -#![no_std] -#![unstable(feature = "sanitizer_runtime_lib", - reason = "internal implementation detail of sanitizers", - issue = "0")] diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index c55911a33f524..581ba74de5b1a 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -34,16 +34,6 @@ features = [ "rustc-dep-of-std" ] # enable build support for integrating into li [dev-dependencies] rand = "0.7" -[target.x86_64-apple-darwin.dependencies] -rustc_asan = { path = "../librustc_asan" } -rustc_tsan = { path = "../librustc_tsan" } - -[target.x86_64-unknown-linux-gnu.dependencies] -rustc_asan = { path = "../librustc_asan" } -rustc_lsan = { path = "../librustc_lsan" } -rustc_msan = { path = "../librustc_msan" } -rustc_tsan = { path = "../librustc_tsan" } - [target.'cfg(any(all(target_arch = "wasm32", not(target_os = "emscripten")), all(target_vendor = "fortanix", target_env = "sgx")))'.dependencies] dlmalloc = { version = "0.1", features = ['rustc-dep-of-std'] } From 93c5639de964ba6ea8cb1e91ef8f18eee7267568 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Mon, 7 Oct 2019 00:00:00 +0000 Subject: [PATCH 03/19] Remove sanitizer_runtime attribute --- .../src/library-features/sanitizer-runtime-lib.md | 5 ----- src/librustc/query/mod.rs | 4 ---- src/librustc_codegen_ssa/base.rs | 4 ---- src/librustc_codegen_ssa/lib.rs | 1 - src/librustc_metadata/cstore_impl.rs | 1 - src/librustc_metadata/encoder.rs | 1 - src/librustc_metadata/schema.rs | 1 - src/libsyntax/feature_gate/active.rs | 3 --- src/libsyntax/feature_gate/builtin_attrs.rs | 5 ----- src/libsyntax/feature_gate/removed.rs | 2 ++ .../feature-gates/feature-gate-sanitizer-runtime.rs | 3 --- .../feature-gate-sanitizer-runtime.stderr | 11 ----------- 12 files changed, 2 insertions(+), 39 deletions(-) delete mode 100644 src/doc/unstable-book/src/library-features/sanitizer-runtime-lib.md delete mode 100644 src/test/ui/feature-gates/feature-gate-sanitizer-runtime.rs delete mode 100644 src/test/ui/feature-gates/feature-gate-sanitizer-runtime.stderr diff --git a/src/doc/unstable-book/src/library-features/sanitizer-runtime-lib.md b/src/doc/unstable-book/src/library-features/sanitizer-runtime-lib.md deleted file mode 100644 index 82ae67fc05ac3..0000000000000 --- a/src/doc/unstable-book/src/library-features/sanitizer-runtime-lib.md +++ /dev/null @@ -1,5 +0,0 @@ -# `sanitizer_runtime_lib` - -This feature is internal to the Rust compiler and is not intended for general use. - ------------------------- diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index fdca6d0e17a1d..53c95e84a762f 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -642,10 +642,6 @@ rustc_queries! { fatal_cycle desc { "checking if the crate has_panic_handler" } } - query is_sanitizer_runtime(_: CrateNum) -> bool { - fatal_cycle - desc { "query a crate is `#![sanitizer_runtime]`" } - } query is_profiler_runtime(_: CrateNum) -> bool { fatal_cycle desc { "query a crate is `#![profiler_runtime]`" } diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index bf687f846357e..06055871027e9 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -721,7 +721,6 @@ impl CrateInfo { panic_runtime: None, compiler_builtins: None, profiler_runtime: None, - sanitizer_runtime: None, is_no_builtins: Default::default(), native_libraries: Default::default(), used_libraries: tcx.native_libraries(LOCAL_CRATE), @@ -757,9 +756,6 @@ impl CrateInfo { if tcx.is_profiler_runtime(cnum) { info.profiler_runtime = Some(cnum); } - if tcx.is_sanitizer_runtime(cnum) { - info.sanitizer_runtime = Some(cnum); - } if tcx.is_no_builtins(cnum) { info.is_no_builtins.insert(cnum); } diff --git a/src/librustc_codegen_ssa/lib.rs b/src/librustc_codegen_ssa/lib.rs index 0221a04b04518..a53612474b4f2 100644 --- a/src/librustc_codegen_ssa/lib.rs +++ b/src/librustc_codegen_ssa/lib.rs @@ -130,7 +130,6 @@ pub struct CrateInfo { pub panic_runtime: Option, pub compiler_builtins: Option, pub profiler_runtime: Option, - pub sanitizer_runtime: Option, pub is_no_builtins: FxHashSet, pub native_libraries: FxHashMap>>, pub crate_name: FxHashMap, diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index d942a19194a14..5d8459c16220b 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -157,7 +157,6 @@ provide! { <'tcx> tcx, def_id, other, cdata, is_compiler_builtins => { cdata.root.compiler_builtins } has_global_allocator => { cdata.root.has_global_allocator } has_panic_handler => { cdata.root.has_panic_handler } - is_sanitizer_runtime => { cdata.root.sanitizer_runtime } is_profiler_runtime => { cdata.root.profiler_runtime } panic_strategy => { cdata.root.panic_strategy } extern_crate => { diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 0dc9f91ae00e1..4c00843f205eb 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -566,7 +566,6 @@ impl<'tcx> EncodeContext<'tcx> { no_builtins: attr::contains_name(&attrs, sym::no_builtins), panic_runtime: attr::contains_name(&attrs, sym::panic_runtime), profiler_runtime: attr::contains_name(&attrs, sym::profiler_runtime), - sanitizer_runtime: attr::contains_name(&attrs, sym::sanitizer_runtime), symbol_mangling_version: tcx.sess.opts.debugging_opts.symbol_mangling_version, crate_deps, diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index ad39aa34fd5c8..e96557c64859e 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -209,7 +209,6 @@ crate struct CrateRoot<'tcx> { pub no_builtins: bool, pub panic_runtime: bool, pub profiler_runtime: bool, - pub sanitizer_runtime: bool, pub symbol_mangling_version: SymbolManglingVersion, } diff --git a/src/libsyntax/feature_gate/active.rs b/src/libsyntax/feature_gate/active.rs index f6e1d6c422499..94b8746fb52e5 100644 --- a/src/libsyntax/feature_gate/active.rs +++ b/src/libsyntax/feature_gate/active.rs @@ -198,9 +198,6 @@ declare_features! ( /// Allows using the `unadjusted` ABI; perma-unstable. (active, abi_unadjusted, "1.16.0", None, None), - /// Allows identifying crates that contain sanitizer runtimes. - (active, sanitizer_runtime, "1.17.0", None, None), - /// Used to identify crates that contain the profiler runtime. (active, profiler_runtime, "1.18.0", None, None), diff --git a/src/libsyntax/feature_gate/builtin_attrs.rs b/src/libsyntax/feature_gate/builtin_attrs.rs index efe84238795a5..1cae924ff0a31 100644 --- a/src/libsyntax/feature_gate/builtin_attrs.rs +++ b/src/libsyntax/feature_gate/builtin_attrs.rs @@ -400,11 +400,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ "the `#[compiler_builtins]` attribute is used to identify the `compiler_builtins` crate \ which contains compiler-rt intrinsics and will never be stable", ), - gated!( - sanitizer_runtime, Whitelisted, template!(Word), - "the `#[sanitizer_runtime]` attribute is used to identify crates that contain the runtime \ - of a sanitizer and will never be stable", - ), gated!( profiler_runtime, Whitelisted, template!(Word), "the `#[profiler_runtime]` attribute is used to identify the `profiler_builtins` crate \ diff --git a/src/libsyntax/feature_gate/removed.rs b/src/libsyntax/feature_gate/removed.rs index 2c29e1ebf1493..445715d3ecaaf 100644 --- a/src/libsyntax/feature_gate/removed.rs +++ b/src/libsyntax/feature_gate/removed.rs @@ -70,6 +70,8 @@ declare_features! ( (removed, pushpop_unsafe, "1.2.0", None, None, None), (removed, needs_allocator, "1.4.0", Some(27389), None, Some("subsumed by `#![feature(allocator_internals)]`")), + /// Allows identifying crates that contain sanitizer runtimes. + (removed, sanitizer_runtime, "1.17.0", None, None, None), (removed, proc_macro_mod, "1.27.0", Some(54727), None, Some("subsumed by `#![feature(proc_macro_hygiene)]`")), (removed, proc_macro_expr, "1.27.0", Some(54727), None, diff --git a/src/test/ui/feature-gates/feature-gate-sanitizer-runtime.rs b/src/test/ui/feature-gates/feature-gate-sanitizer-runtime.rs deleted file mode 100644 index 3b972c117a6ff..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-sanitizer-runtime.rs +++ /dev/null @@ -1,3 +0,0 @@ -#![sanitizer_runtime] //~ ERROR the `#[sanitizer_runtime]` attribute is - -fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-sanitizer-runtime.stderr b/src/test/ui/feature-gates/feature-gate-sanitizer-runtime.stderr deleted file mode 100644 index b13ec215f8c08..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-sanitizer-runtime.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0658]: the `#[sanitizer_runtime]` attribute is used to identify crates that contain the runtime of a sanitizer and will never be stable - --> $DIR/feature-gate-sanitizer-runtime.rs:1:1 - | -LL | #![sanitizer_runtime] - | ^^^^^^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(sanitizer_runtime)]` to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. From d56ab6dfba6a930293a643ffb8ed9f89ba1ee782 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Sun, 6 Oct 2019 00:00:00 +0000 Subject: [PATCH 04/19] Link sanitizer runtimes instead of injecting crate dependencies --- src/bootstrap/check.rs | 2 +- src/bootstrap/compile.rs | 131 +++++++++++++----- src/bootstrap/doc.rs | 2 +- src/bootstrap/native.rs | 7 + src/bootstrap/test.rs | 2 +- src/librustc/session/mod.rs | 11 ++ src/librustc_codegen_ssa/back/link.rs | 88 ++++++------ src/librustc_metadata/creader.rs | 102 +------------- .../sanitizer-address/Makefile | 2 +- .../sanitizer-invalid-target/Makefile | 2 +- .../run-make-fulldeps/sanitizer-leak/Makefile | 2 +- .../sanitizer-memory/Makefile | 2 +- 12 files changed, 165 insertions(+), 188 deletions(-) diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index df1c72575846b..9be1d29663022 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -48,7 +48,7 @@ impl Step for Std { let compiler = builder.compiler(0, builder.config.build); let mut cargo = builder.cargo(compiler, Mode::Std, target, cargo_subcommand(builder.kind)); - std_cargo(builder, &compiler, target, &mut cargo); + std_cargo(builder, target, &mut cargo); builder.info(&format!("Checking std artifacts ({} -> {})", &compiler.host, target)); run_cargo(builder, diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index da8d43ed49b7f..0eb5be718ae57 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -94,7 +94,7 @@ impl Step for Std { target_deps.extend(copy_third_party_objects(builder, &compiler, target).into_iter()); let mut cargo = builder.cargo(compiler, Mode::Std, target, "build"); - std_cargo(builder, &compiler, target, &mut cargo); + std_cargo(builder, target, &mut cargo); builder.info(&format!("Building stage{} std artifacts ({} -> {})", compiler.stage, &compiler.host, target)); @@ -163,7 +163,6 @@ fn copy_third_party_objects(builder: &Builder<'_>, compiler: &Compiler, target: /// Configure cargo to compile the standard library, adding appropriate env vars /// and such. pub fn std_cargo(builder: &Builder<'_>, - compiler: &Compiler, target: Interned, cargo: &mut Cargo) { if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") { @@ -208,21 +207,6 @@ pub fn std_cargo(builder: &Builder<'_>, let mut features = builder.std_features(); features.push_str(&compiler_builtins_c_feature); - if compiler.stage != 0 && builder.config.sanitizers { - // This variable is used by the sanitizer runtime crates, e.g. - // rustc_lsan, to build the sanitizer runtime from C code - // When this variable is missing, those crates won't compile the C code, - // so we don't set this variable during stage0 where llvm-config is - // missing - // We also only build the runtimes when --enable-sanitizers (or its - // config.toml equivalent) is used - let llvm_config = builder.ensure(native::Llvm { - target: builder.config.build, - }); - cargo.env("LLVM_CONFIG", llvm_config); - cargo.env("RUSTC_BUILD_SANITIZERS", "1"); - } - cargo.arg("--features").arg(features) .arg("--manifest-path") .arg(builder.src.join("src/libtest/Cargo.toml")); @@ -281,30 +265,105 @@ impl Step for StdLink { let hostdir = builder.sysroot_libdir(target_compiler, compiler.host); add_to_sysroot(builder, &libdir, &hostdir, &libstd_stamp(builder, compiler, target)); - if builder.config.sanitizers && compiler.stage != 0 && target == "x86_64-apple-darwin" { - // The sanitizers are only built in stage1 or above, so the dylibs will - // be missing in stage0 and causes panic. See the `std()` function above - // for reason why the sanitizers are not built in stage0. - copy_apple_sanitizer_dylibs(builder, &builder.native_dir(target), "osx", &libdir); + if builder.config.sanitizers && compiler.stage != 0 { + // The sanitizers are only copied in stage1 or above, + // to avoid creating dependency on LLVM. + copy_sanitizers(builder, &target_compiler, target); } } } -fn copy_apple_sanitizer_dylibs( - builder: &Builder<'_>, - native_dir: &Path, - platform: &str, - into: &Path, -) { - for &sanitizer in &["asan", "tsan"] { - let filename = format!("lib__rustc__clang_rt.{}_{}_dynamic.dylib", sanitizer, platform); - let mut src_path = native_dir.join(sanitizer); - src_path.push("build"); - src_path.push("lib"); - src_path.push("darwin"); - src_path.push(&filename); - builder.copy(&src_path, &into.join(filename)); +/// Copies sanitizer runtime libraries into target libdir. +fn copy_sanitizers(builder: &Builder<'_>, target_compiler: &Compiler, target: Interned) { + let sanitizers = supported_sanitizers(target); + if sanitizers.is_empty() { + return; + } + + let llvm_config: PathBuf = builder.ensure(native::Llvm { + target: target_compiler.host, + }); + if builder.config.dry_run { + return; + } + + // The compiler-rt installs sanitizer runtimes into clang resource directory. + let clang_resourcedir = clang_resourcedir(&llvm_config); + let libdir = builder.sysroot_libdir(*target_compiler, target); + + for (path, name) in &sanitizers { + let src = clang_resourcedir.join(path); + let dst = libdir.join(name); + if !src.exists() { + println!("Ignoring missing runtime: {}", src.display()); + continue; + } + builder.copy(&src, &dst); + + if target == "x86_64-apple-darwin" { + // Update the library install name reflect the fact it has been renamed. + let status = Command::new("install_name_tool") + .arg("-id") + .arg(format!("@rpath/{}", name)) + .arg(&dst) + .status() + .expect("failed to execute `install_name_tool`"); + assert!(status.success()); + } + } +} + +/// Returns path to clang's resource directory. +fn clang_resourcedir(llvm_config: &Path) -> PathBuf { + let llvm_version = output(Command::new(&llvm_config).arg("--version")); + let llvm_version = llvm_version.trim(); + let llvm_libdir = output(Command::new(&llvm_config).arg("--libdir")); + let llvm_libdir = PathBuf::from(llvm_libdir.trim()); + + // Determine CLANG_VERSION by stripping LLVM_VERSION_SUFFIX from LLVM_VERSION. + let mut non_digits = 0; + let mut third_non_digit = llvm_version.len(); + for (i, c) in llvm_version.char_indices() { + if !c.is_digit(10) { + non_digits += 1; + if non_digits == 3 { + third_non_digit = i; + break; + } + } + } + let clang_version = &llvm_version[..third_non_digit]; + llvm_libdir.join("clang").join(&clang_version) +} + +/// Returns a list of paths to sanitizer libraries supported on given target, +/// and corresponding names we plan to give them when placed in target libdir. +/// +/// Returned paths are relative to clang's resource directory. +fn supported_sanitizers(target: Interned) -> Vec<(PathBuf, String)> { + let sanitizers = &["asan", "lsan", "msan", "tsan"]; + let mut result = Vec::new(); + match &*target { + "x86_64-apple-darwin" => { + let srcdir = Path::new("lib/darwin"); + for s in sanitizers { + let src = format!("libclang_rt.{}_osx_dynamic.dylib", s); + let dst = format!("librustc_rt.{}.dylib", s); + result.push((srcdir.join(src), dst)); + } + + } + "x86_64-unknown-linux-gnu" => { + let srcdir = Path::new("lib/linux"); + for s in sanitizers { + let src = format!("libclang_rt.{}-x86_64.a", s); + let dst = format!("librustc_rt.{}.a", s); + result.push((srcdir.join(src), dst)); + } + } + _ => {} } + result } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 4ee8cd2485c02..5e68b9d27c2d8 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -458,7 +458,7 @@ impl Step for Std { let run_cargo_rustdoc_for = |package: &str| { let mut cargo = builder.cargo(compiler, Mode::Std, target, "rustdoc"); - compile::std_cargo(builder, &compiler, target, &mut cargo); + compile::std_cargo(builder, target, &mut cargo); // Keep a whitelist so we do not build internal stdlib crates, these will be // build by the rustc step later if enabled. diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 97cdd25680162..fe65f492aa578 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -186,6 +186,13 @@ impl Step for Llvm { enabled_llvm_projects.push("compiler-rt"); } + if builder.config.sanitizers { + enabled_llvm_projects.push("compiler-rt"); + cfg.define("COMPILER_RT_BUILD_SANITIZERS", "ON"); + // Avoids building instrumented version of libcxx. + cfg.define("COMPILER_RT_USE_LIBCXX", "OFF"); + } + if builder.config.lldb_enabled { enabled_llvm_projects.push("clang"); enabled_llvm_projects.push("lldb"); diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 60f0dccdb070e..6b4e1c2dc31d0 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1764,7 +1764,7 @@ impl Step for Crate { let mut cargo = builder.cargo(compiler, mode, target, test_kind.subcommand()); match mode { Mode::Std => { - compile::std_cargo(builder, &compiler, target, &mut cargo); + compile::std_cargo(builder, target, &mut cargo); } Mode::Rustc => { builder.ensure(compile::Rustc { compiler, target }); diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index bd2460cfab116..18629f751fce9 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -1297,6 +1297,17 @@ fn validate_commandline_args_with_session_available(sess: &Session) { with `-Cpanic=unwind` on Windows when targeting MSVC. \ See https://github.com/rust-lang/rust/issues/61002 for details."); } + + // Sanitizers can only be used on some tested platforms. + if let Some(ref sanitizer) = sess.opts.debugging_opts.sanitizer { + const SUPPORTED_TARGETS: &[&str] = &["x86_64-unknown-linux-gnu", "x86_64-apple-darwin"]; + if !SUPPORTED_TARGETS.contains(&&*sess.opts.target_triple.triple()) { + sess.err(&format!("{:?}Sanitizer only works with the `{}` target", + sanitizer, + SUPPORTED_TARGETS.join("` or `") + )); + } + } } /// Hash value constructed out of all the `-C metadata` arguments passed to the diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index 1c5d3b1a890ee..774beb631f872 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -522,6 +522,7 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(sess: &'a Session, { let mut linker = codegen_results.linker_info.to_linker(cmd, &sess, flavor, target_cpu); + link_sanitizer_runtime(sess, crate_type, &mut *linker); link_args::(&mut *linker, flavor, sess, crate_type, tmpdir, out_filename, codegen_results); cmd = linker.finalize(); @@ -725,6 +726,49 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(sess: &'a Session, } } +fn link_sanitizer_runtime(sess: &Session, + crate_type: config::CrateType, + linker: &mut dyn Linker) { + let sanitizer = match &sess.opts.debugging_opts.sanitizer { + Some(s) => s, + None => return, + }; + + if crate_type != config::CrateType::Executable { + return; + } + + let name = match sanitizer { + Sanitizer::Address => "asan", + Sanitizer::Leak => "lsan", + Sanitizer::Memory => "msan", + Sanitizer::Thread => "tsan", + }; + + let default_sysroot = filesearch::get_or_default_sysroot(); + let default_tlib = filesearch::make_target_lib_path( + &default_sysroot, sess.opts.target_triple.triple()); + + match sess.opts.target_triple.triple() { + "x86_64-apple-darwin" => { + // On Apple platforms, the sanitizer is always built as a dylib, and + // LLVM will link to `@rpath/*.dylib`, so we need to specify an + // rpath to the library as well (the rpath should be absolute, see + // PR #41352 for details). + let filename = format!("librustc_rt.{}.dylib", name); + let rpath = default_tlib.to_str().expect("non-utf8 component in path"); + linker.args(&["-Wl,-rpath".into(), "-Xlinker".into(), rpath.into()]); + linker.link_dylib(Symbol::intern(&filename)); + } + "x86_64-unknown-linux-gnu" => { + let filename = format!("librustc_rt.{}.a", name); + let path = default_tlib.join(&filename); + linker.link_whole_rlib(&path); + } + _ => {} + } +} + /// Returns a boolean indicating whether the specified crate should be ignored /// during LTO. /// @@ -1391,11 +1435,6 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>( _ if codegen_results.crate_info.profiler_runtime == Some(cnum) => { add_static_crate::(cmd, sess, codegen_results, tmpdir, crate_type, cnum); } - _ if codegen_results.crate_info.sanitizer_runtime == Some(cnum) && - crate_type == config::CrateType::Executable => { - // Link the sanitizer runtimes only if we are actually producing an executable - link_sanitizer_runtime::(cmd, sess, codegen_results, tmpdir, cnum); - } // compiler-builtins are always placed last to ensure that they're // linked correctly. _ if codegen_results.crate_info.compiler_builtins == Some(cnum) => { @@ -1435,45 +1474,6 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>( } } - // We must link the sanitizer runtime using -Wl,--whole-archive but since - // it's packed in a .rlib, it contains stuff that are not objects that will - // make the linker error. So we must remove those bits from the .rlib before - // linking it. - fn link_sanitizer_runtime<'a, B: ArchiveBuilder<'a>>(cmd: &mut dyn Linker, - sess: &'a Session, - codegen_results: &CodegenResults, - tmpdir: &Path, - cnum: CrateNum) { - let src = &codegen_results.crate_info.used_crate_source[&cnum]; - let cratepath = &src.rlib.as_ref().unwrap().0; - - if sess.target.target.options.is_like_osx { - // On Apple platforms, the sanitizer is always built as a dylib, and - // LLVM will link to `@rpath/*.dylib`, so we need to specify an - // rpath to the library as well (the rpath should be absolute, see - // PR #41352 for details). - // - // FIXME: Remove this logic into librustc_*san once Cargo supports it - let rpath = cratepath.parent().unwrap(); - let rpath = rpath.to_str().expect("non-utf8 component in path"); - cmd.args(&["-Wl,-rpath".into(), "-Xlinker".into(), rpath.into()]); - } - - let dst = tmpdir.join(cratepath.file_name().unwrap()); - let mut archive = ::new(sess, &dst, Some(cratepath)); - archive.update_symbols(); - - for f in archive.src_files() { - if f.ends_with(RLIB_BYTECODE_EXTENSION) || f == METADATA_FILENAME { - archive.remove_file(&f); - } - } - - archive.build(); - - cmd.link_whole_rlib(&dst); - } - // Adds the static "rlib" versions of all crates to the command line. // There's a bit of magic which happens here specifically related to LTO and // dynamic libraries. Specifically: diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index f0a68058de8ca..a7b83c18549c2 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -11,7 +11,7 @@ use rustc::dep_graph::DepNodeIndex; use rustc::middle::cstore::DepKind; use rustc::mir::interpret::AllocDecodingState; use rustc::session::{Session, CrateDisambiguator}; -use rustc::session::config::{Sanitizer, self}; +use rustc::session::config; use rustc_target::spec::{PanicStrategy, TargetTriple}; use rustc::session::search_paths::PathKind; use rustc::middle::cstore::{CrateSource, ExternCrate, ExternCrateSource, MetadataLoaderDyn}; @@ -599,105 +599,6 @@ impl<'a> CrateLoader<'a> { &|data| data.root.needs_panic_runtime); } - fn inject_sanitizer_runtime(&mut self) { - if let Some(ref sanitizer) = self.sess.opts.debugging_opts.sanitizer { - // Sanitizers can only be used on some tested platforms with - // executables linked to `std` - const ASAN_SUPPORTED_TARGETS: &[&str] = &["x86_64-unknown-linux-gnu", - "x86_64-apple-darwin"]; - const TSAN_SUPPORTED_TARGETS: &[&str] = &["x86_64-unknown-linux-gnu", - "x86_64-apple-darwin"]; - const LSAN_SUPPORTED_TARGETS: &[&str] = &["x86_64-unknown-linux-gnu"]; - const MSAN_SUPPORTED_TARGETS: &[&str] = &["x86_64-unknown-linux-gnu"]; - - let supported_targets = match *sanitizer { - Sanitizer::Address => ASAN_SUPPORTED_TARGETS, - Sanitizer::Thread => TSAN_SUPPORTED_TARGETS, - Sanitizer::Leak => LSAN_SUPPORTED_TARGETS, - Sanitizer::Memory => MSAN_SUPPORTED_TARGETS, - }; - if !supported_targets.contains(&&*self.sess.opts.target_triple.triple()) { - self.sess.err(&format!("{:?}Sanitizer only works with the `{}` target", - sanitizer, - supported_targets.join("` or `") - )); - return - } - - // firstyear 2017 - during testing I was unable to access an OSX machine - // to make this work on different crate types. As a result, today I have - // only been able to test and support linux as a target. - if self.sess.opts.target_triple.triple() == "x86_64-unknown-linux-gnu" { - if !self.sess.crate_types.borrow().iter().all(|ct| { - match *ct { - // Link the runtime - config::CrateType::Executable => true, - // This crate will be compiled with the required - // instrumentation pass - config::CrateType::Staticlib | - config::CrateType::Rlib | - config::CrateType::Dylib | - config::CrateType::Cdylib => - false, - _ => { - self.sess.err(&format!("Only executables, staticlibs, \ - cdylibs, dylibs and rlibs can be compiled with \ - `-Z sanitizer`")); - false - } - } - }) { - return - } - } else { - if !self.sess.crate_types.borrow().iter().all(|ct| { - match *ct { - // Link the runtime - config::CrateType::Executable => true, - // This crate will be compiled with the required - // instrumentation pass - config::CrateType::Rlib => false, - _ => { - self.sess.err(&format!("Only executables and rlibs can be \ - compiled with `-Z sanitizer`")); - false - } - } - }) { - return - } - } - - let mut uses_std = false; - self.cstore.iter_crate_data(|_, data| { - if data.root.name == sym::std { - uses_std = true; - } - }); - - if uses_std { - let name = Symbol::intern(match sanitizer { - Sanitizer::Address => "rustc_asan", - Sanitizer::Leak => "rustc_lsan", - Sanitizer::Memory => "rustc_msan", - Sanitizer::Thread => "rustc_tsan", - }); - info!("loading sanitizer: {}", name); - - let cnum = self.resolve_crate(name, DUMMY_SP, DepKind::Explicit, None); - let data = self.cstore.get_crate_data(cnum); - - // Sanity check the loaded crate to ensure it is indeed a sanitizer runtime - if !data.root.sanitizer_runtime { - self.sess.err(&format!("the crate `{}` is not a sanitizer runtime", - name)); - } - } else { - self.sess.err("Must link std to be compiled with `-Z sanitizer`"); - } - } - } - fn inject_profiler_runtime(&mut self) { if self.sess.opts.debugging_opts.profile || self.sess.opts.cg.profile_generate.enabled() @@ -854,7 +755,6 @@ impl<'a> CrateLoader<'a> { } pub fn postprocess(&mut self, krate: &ast::Crate) { - self.inject_sanitizer_runtime(); self.inject_profiler_runtime(); self.inject_allocator_crate(krate); self.inject_panic_runtime(krate); diff --git a/src/test/run-make-fulldeps/sanitizer-address/Makefile b/src/test/run-make-fulldeps/sanitizer-address/Makefile index 3a377c32993d5..6715ef16eb620 100644 --- a/src/test/run-make-fulldeps/sanitizer-address/Makefile +++ b/src/test/run-make-fulldeps/sanitizer-address/Makefile @@ -23,7 +23,7 @@ endif endif all: - $(RUSTC) -g -Z sanitizer=address -Z print-link-args $(EXTRA_RUSTFLAG) overflow.rs | $(CGREP) librustc_asan + $(RUSTC) -g -Z sanitizer=address -Z print-link-args $(EXTRA_RUSTFLAG) overflow.rs | $(CGREP) librustc_rt.asan # Verify that stack buffer overflow is detected: $(TMPDIR)/overflow 2>&1 | $(CGREP) stack-buffer-overflow # Verify that variable name is included in address sanitizer report: diff --git a/src/test/run-make-fulldeps/sanitizer-invalid-target/Makefile b/src/test/run-make-fulldeps/sanitizer-invalid-target/Makefile index df8afee15ce07..2a23f0fe3d4ef 100644 --- a/src/test/run-make-fulldeps/sanitizer-invalid-target/Makefile +++ b/src/test/run-make-fulldeps/sanitizer-invalid-target/Makefile @@ -2,4 +2,4 @@ all: $(RUSTC) -Z sanitizer=leak --target i686-unknown-linux-gnu hello.rs 2>&1 | \ - $(CGREP) 'LeakSanitizer only works with the `x86_64-unknown-linux-gnu` target' + $(CGREP) 'LeakSanitizer only works with the `x86_64-unknown-linux-gnu` or `x86_64-apple-darwin` target' diff --git a/src/test/run-make-fulldeps/sanitizer-leak/Makefile b/src/test/run-make-fulldeps/sanitizer-leak/Makefile index 101e8272ab91e..070a4948e9c1c 100644 --- a/src/test/run-make-fulldeps/sanitizer-leak/Makefile +++ b/src/test/run-make-fulldeps/sanitizer-leak/Makefile @@ -7,5 +7,5 @@ # FIXME(#46126) ThinLTO for libstd broke this test all: - $(RUSTC) -C opt-level=1 -g -Z sanitizer=leak -Z print-link-args leak.rs | $(CGREP) librustc_lsan + $(RUSTC) -C opt-level=1 -g -Z sanitizer=leak -Z print-link-args leak.rs | $(CGREP) librustc_rt.lsan $(TMPDIR)/leak 2>&1 | $(CGREP) 'detected memory leaks' diff --git a/src/test/run-make-fulldeps/sanitizer-memory/Makefile b/src/test/run-make-fulldeps/sanitizer-memory/Makefile index b3376f8a72358..cf41390d9f7f1 100644 --- a/src/test/run-make-fulldeps/sanitizer-memory/Makefile +++ b/src/test/run-make-fulldeps/sanitizer-memory/Makefile @@ -5,5 +5,5 @@ # only-x86_64 all: - $(RUSTC) -g -Z sanitizer=memory -Z print-link-args uninit.rs | $(CGREP) librustc_msan + $(RUSTC) -g -Z sanitizer=memory -Z print-link-args uninit.rs | $(CGREP) librustc_rt.msan $(TMPDIR)/uninit 2>&1 | $(CGREP) use-of-uninitialized-value From 160791bc972fa3ddfae2a83fe34c1e5816fa7685 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Tue, 8 Oct 2019 00:00:00 +0000 Subject: [PATCH 05/19] Enable sanitizer-leak test case --- src/test/run-make-fulldeps/sanitizer-leak/Makefile | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/test/run-make-fulldeps/sanitizer-leak/Makefile b/src/test/run-make-fulldeps/sanitizer-leak/Makefile index 070a4948e9c1c..2f485ae4fa4c3 100644 --- a/src/test/run-make-fulldeps/sanitizer-leak/Makefile +++ b/src/test/run-make-fulldeps/sanitizer-leak/Makefile @@ -3,8 +3,6 @@ # needs-sanitizer-support # only-linux # only-x86_64 -# ignore-test -# FIXME(#46126) ThinLTO for libstd broke this test all: $(RUSTC) -C opt-level=1 -g -Z sanitizer=leak -Z print-link-args leak.rs | $(CGREP) librustc_rt.lsan From 7d6f8691ac96cf34c1e2b5e36e0a0c11ca5236d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Wed, 16 Oct 2019 00:00:00 +0000 Subject: [PATCH 06/19] Document sanitizers in unstable-book --- .../src/compiler-flags/sanitizer.md | 163 ++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 src/doc/unstable-book/src/compiler-flags/sanitizer.md diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md new file mode 100644 index 0000000000000..cbb90bd3bb331 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md @@ -0,0 +1,163 @@ +# `sanitizer` + +The tracking issue for this feature is: [#39699](https://github.com/rust-lang/rust/issues/39699). + +------------------------ + +This feature allows for use of one of following sanitizers: + +* [AddressSanitizer][clang-asan] a faster memory error detector. Can + detect out-of-bounds access to heap, stack, and globals, use after free, use + after return, double free, invalid free, memory leaks. +* [LeakSanitizer][clang-lsan] a run-time memory leak detector. +* [MemorySanitizer][clang-msan] a detector of uninitialized reads. +* [ThreadSanitizer][clang-tsan] a fast data race detector. + +To enable a sanitizer compile with `-Zsanitizer=...` option, where value is one +of `address`, `leak`, `memory` or `thread`. + +# Examples + +This sections show various issues that can be detected with sanitizers. For +simplicity, the examples are prepared under assumption that optimization level +used is zero. + +## AddressSanitizer + +Stack buffer overflow: + +```shell +$ cat a.rs +fn main() { + let xs = [0, 1, 2, 3]; + let _y = unsafe { *xs.as_ptr().offset(4) }; +} +$ rustc -Zsanitizer=address a.rs +$ ./a +================================================================= +==10029==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffcc15f43d0 at pc 0x55f77dc015c5 bp 0x7ffcc15f4390 sp 0x7ffcc15f4388 +READ of size 4 at 0x7ffcc15f43d0 thread T0 + #0 0x55f77dc015c4 in a::main::hab3bd2a745c2d0ac (/tmp/a+0xa5c4) + #1 0x55f77dc01cdb in std::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::haa8c76d1faa7b7ca (/tmp/a+0xacdb) + #2 0x55f77dc90f02 in std::rt::lang_start_internal::_$u7b$$u7b$closure$u7d$$u7d$::hfeb9a1aef9ac820d /rustc/c27f7568bc74c418996892028a629eed5a7f5f00/src/libstd/rt.rs:48:12 + #3 0x55f77dc90f02 in std::panicking::try::do_call::h12f0919717b8e0a6 /rustc/c27f7568bc74c418996892028a629eed5a7f5f00/src/libstd/panicking.rs:288:39 + #4 0x55f77dc926c9 in __rust_maybe_catch_panic /rustc/c27f7568bc74c418996892028a629eed5a7f5f00/src/libpanic_unwind/lib.rs:80:7 + #5 0x55f77dc9197c in std::panicking::try::h413b21cdcd6cfd86 /rustc/c27f7568bc74c418996892028a629eed5a7f5f00/src/libstd/panicking.rs:267:12 + #6 0x55f77dc9197c in std::panic::catch_unwind::hc5cc8ef2fd73424d /rustc/c27f7568bc74c418996892028a629eed5a7f5f00/src/libstd/panic.rs:396:8 + #7 0x55f77dc9197c in std::rt::lang_start_internal::h2039f418ab92218f /rustc/c27f7568bc74c418996892028a629eed5a7f5f00/src/libstd/rt.rs:47:24 + #8 0x55f77dc01c61 in std::rt::lang_start::ha905d28f6b61d691 (/tmp/a+0xac61) + #9 0x55f77dc0163a in main (/tmp/a+0xa63a) + #10 0x7f9b3cf5bbba in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x26bba) + #11 0x55f77dc01289 in _start (/tmp/a+0xa289) + +Address 0x7ffcc15f43d0 is located in stack of thread T0 at offset 48 in frame + #0 0x55f77dc0135f in a::main::hab3bd2a745c2d0ac (/tmp/a+0xa35f) + + This frame has 1 object(s): + [32, 48) 'xs' <== Memory access at offset 48 overflows this variable +HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork + (longjmp and C++ exceptions *are* supported) +SUMMARY: AddressSanitizer: stack-buffer-overflow (/tmp/a+0xa5c4) in a::main::hab3bd2a745c2d0ac +Shadow bytes around the buggy address: + 0x1000182b6820: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x1000182b6830: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x1000182b6840: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x1000182b6850: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x1000182b6860: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +=>0x1000182b6870: 00 00 00 00 f1 f1 f1 f1 00 00[f3]f3 00 00 00 00 + 0x1000182b6880: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x1000182b6890: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x1000182b68a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x1000182b68b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x1000182b68c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +Shadow byte legend (one shadow byte represents 8 application bytes): + Addressable: 00 + Partially addressable: 01 02 03 04 05 06 07 + Heap left redzone: fa + Freed heap region: fd + Stack left redzone: f1 + Stack mid redzone: f2 + Stack right redzone: f3 + Stack after return: f5 + Stack use after scope: f8 + Global redzone: f9 + Global init order: f6 + Poisoned by user: f7 + Container overflow: fc + Array cookie: ac + Intra object redzone: bb + ASan internal: fe + Left alloca redzone: ca + Right alloca redzone: cb + Shadow gap: cc +==10029==ABORTING +``` + +## MemorySanitizer + +Use of uninitialized memory. Note that we are using `-Zbuild-std` to instrument +standard library, and passing `-msan-track-origins=2` to the LLVM to track +origins of uninitialized memory: + +```shell +$ cat src/main.rs +use std::mem::MaybeUninit; + +fn main() { + unsafe { + let a = MaybeUninit::<[usize; 4]>::uninit(); + let a = a.assume_init(); + println!("{}", a[2]); + } +} + +$ env RUSTFLAGS="-Zsanitizer=memory -Cllvm-args=-msan-track-origins=2" cargo -Zbuild-std run --target x86_64-unknown-linux-gnu +==9416==WARNING: MemorySanitizer: use-of-uninitialized-value + #0 0x560c04f7488a in core::fmt::num::imp::fmt_u64::haa293b0b098501ca $RUST/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/src/rust/src/libcore/fmt/num.rs:202:16 +... + Uninitialized value was stored to memory at + #0 0x560c04ae898a in __msan_memcpy.part.0 $RUST/src/llvm-project/compiler-rt/lib/msan/msan_interceptors.cc:1558:3 + #1 0x560c04b2bf88 in memory::main::hd2333c1899d997f5 $CWD/src/main.rs:6:16 + + Uninitialized value was created by an allocation of 'a' in the stack frame of function '_ZN6memory4main17hd2333c1899d997f5E' + #0 0x560c04b2bc50 in memory::main::hd2333c1899d997f5 $CWD/src/main.rs:3 +``` + + +# Instrumentation of external dependencies and std + +The sanitizers to varying degrees work correctly with partially instrumented +code. On the one extreme is LeakSanitizer that doesn't use any compile time +instrumentation, on the other is MemorySanitizer that requires that all program +code to be instrumented (failing to achieve that will inevitably result in +false positives). + +It is strongly recommended to combine sanitizers with recompiled and +instrumented standard library, for example using [cargo `-Zbuild-std` +functionality][build-std]. + +[build-std]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-std + +# Build scripts and procedural macros + +Use of sanitizers together with build scripts and procedural macros is +technically possible, but in almost all cases it would be best avoided. This +is especially true for procedural macros which would require an instrumented +version of rustc. + +In more practical terms when using cargo always remember to pass `--target` +flag, so that rustflags will not be applied to build scripts and procedural +macros. + +# Additional Information + +* [Sanitizers project page](https://github.com/google/sanitizers/wiki/) +* [AddressSanitizer in Clang][clang-asan] +* [LeakSanitizer in Clang][clang-lsan] +* [MemorySanitizer in Clang][clang-msan] +* [ThreadSanitizer in Clang][clang-tsan] + +[clang-asan]: https://clang.llvm.org/docs/AddressSanitizer.html +[clang-lsan]: https://clang.llvm.org/docs/LeakSanitizer.html +[clang-msan]: https://clang.llvm.org/docs/MemorySanitizer.html +[clang-tsan]: https://clang.llvm.org/docs/ThreadSanitizer.html From e42800b21818a4b144cf56c0ac7effa5b71cead6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Sun, 27 Oct 2019 00:00:00 +0000 Subject: [PATCH 07/19] Copy sanitizer runtimes as part of copy_third_party_objects --- src/bootstrap/compile.rs | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 0eb5be718ae57..9cd208a1d137c 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -157,6 +157,12 @@ fn copy_third_party_objects(builder: &Builder<'_>, compiler: &Compiler, target: copy_and_stamp(Path::new(&src), "libunwind.a"); } + if builder.config.sanitizers && compiler.stage != 0 { + // The sanitizers are only copied in stage1 or above, + // to avoid creating dependency on LLVM. + target_deps.extend(copy_sanitizers(builder, &compiler, target)); + } + target_deps } @@ -264,32 +270,30 @@ impl Step for StdLink { let libdir = builder.sysroot_libdir(target_compiler, target); let hostdir = builder.sysroot_libdir(target_compiler, compiler.host); add_to_sysroot(builder, &libdir, &hostdir, &libstd_stamp(builder, compiler, target)); - - if builder.config.sanitizers && compiler.stage != 0 { - // The sanitizers are only copied in stage1 or above, - // to avoid creating dependency on LLVM. - copy_sanitizers(builder, &target_compiler, target); - } } } /// Copies sanitizer runtime libraries into target libdir. -fn copy_sanitizers(builder: &Builder<'_>, target_compiler: &Compiler, target: Interned) { +fn copy_sanitizers(builder: &Builder<'_>, + compiler: &Compiler, + target: Interned) -> Vec { + let mut target_deps = Vec::new(); + let sanitizers = supported_sanitizers(target); if sanitizers.is_empty() { - return; + return target_deps; } let llvm_config: PathBuf = builder.ensure(native::Llvm { - target: target_compiler.host, + target: compiler.host, }); if builder.config.dry_run { - return; + return target_deps; } // The compiler-rt installs sanitizer runtimes into clang resource directory. let clang_resourcedir = clang_resourcedir(&llvm_config); - let libdir = builder.sysroot_libdir(*target_compiler, target); + let libdir = builder.sysroot_libdir(*compiler, target); for (path, name) in &sanitizers { let src = clang_resourcedir.join(path); @@ -310,7 +314,11 @@ fn copy_sanitizers(builder: &Builder<'_>, target_compiler: &Compiler, target: In .expect("failed to execute `install_name_tool`"); assert!(status.success()); } + + target_deps.push(dst); } + + target_deps } /// Returns path to clang's resource directory. From 58b67c88119970b7c96f678e3afaab00f086f612 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 28 Oct 2019 16:58:27 -0700 Subject: [PATCH 08/19] Use structured suggestion for unnecessary bounds in type aliases --- src/librustc_lint/builtin.rs | 17 ++++-- .../associated-type-bounds/type-alias.stderr | 60 +++++++++++++++---- .../ui/privacy/private-in-public-warn.stderr | 10 +++- .../trivial-bounds-inconsistent.stderr | 5 +- src/test/ui/type/type-alias-bounds.stderr | 45 +++++++++++--- 5 files changed, 109 insertions(+), 28 deletions(-) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 7c19449f96b86..e3c3966c2f5e0 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -1125,8 +1125,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeAliasBounds { .map(|pred| pred.span()).collect(); let mut err = cx.struct_span_lint(TYPE_ALIAS_BOUNDS, spans, "where clauses are not enforced in type aliases"); - err.help("the clause will not be checked when the type alias is used, \ - and should be removed"); + err.span_suggestion( + type_alias_generics.where_clause.span_for_predicates_or_empty_place(), + "the clause will not be checked when the type alias is used, and should be removed", + String::new(), + Applicability::MachineApplicable, + ); if !suggested_changing_assoc_types { TypeAliasBounds::suggest_changing_assoc_types(ty, &mut err); suggested_changing_assoc_types = true; @@ -1136,14 +1140,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeAliasBounds { // The parameters must not have bounds for param in type_alias_generics.params.iter() { let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect(); + let suggestion = spans.iter().map(|sp| { + let start = param.span.between(*sp); // Include the `:` in `T: Bound`. + (start.to(*sp), String::new()) + }).collect(); if !spans.is_empty() { let mut err = cx.struct_span_lint( TYPE_ALIAS_BOUNDS, spans, "bounds on generic parameters are not enforced in type aliases", ); - err.help("the bound will not be checked when the type alias is used, \ - and should be removed"); + let msg = "the bound will not be checked when the type alias is used, \ + and should be removed"; + err.multipart_suggestion(&msg, suggestion, Applicability::MachineApplicable); if !suggested_changing_assoc_types { TypeAliasBounds::suggest_changing_assoc_types(ty, &mut err); suggested_changing_assoc_types = true; diff --git a/src/test/ui/associated-type-bounds/type-alias.stderr b/src/test/ui/associated-type-bounds/type-alias.stderr index a3fa97f54e385..7f58f7f73e38c 100644 --- a/src/test/ui/associated-type-bounds/type-alias.stderr +++ b/src/test/ui/associated-type-bounds/type-alias.stderr @@ -5,7 +5,10 @@ LL | type _TaWhere1 where T: Iterator = T; | ^^^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(type_alias_bounds)]` on by default - = help: the clause will not be checked when the type alias is used, and should be removed +help: the clause will not be checked when the type alias is used, and should be removed + | +LL | type _TaWhere1 = T; + | -- warning: where clauses are not enforced in type aliases --> $DIR/type-alias.rs:6:25 @@ -13,7 +16,10 @@ warning: where clauses are not enforced in type aliases LL | type _TaWhere2 where T: Iterator = T; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: the clause will not be checked when the type alias is used, and should be removed +help: the clause will not be checked when the type alias is used, and should be removed + | +LL | type _TaWhere2 = T; + | -- warning: where clauses are not enforced in type aliases --> $DIR/type-alias.rs:7:25 @@ -21,7 +27,10 @@ warning: where clauses are not enforced in type aliases LL | type _TaWhere3 where T: Iterator = T; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: the clause will not be checked when the type alias is used, and should be removed +help: the clause will not be checked when the type alias is used, and should be removed + | +LL | type _TaWhere3 = T; + | -- warning: where clauses are not enforced in type aliases --> $DIR/type-alias.rs:8:25 @@ -29,7 +38,10 @@ warning: where clauses are not enforced in type aliases LL | type _TaWhere4 where T: Iterator = T; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: the clause will not be checked when the type alias is used, and should be removed +help: the clause will not be checked when the type alias is used, and should be removed + | +LL | type _TaWhere4 = T; + | -- warning: where clauses are not enforced in type aliases --> $DIR/type-alias.rs:9:25 @@ -37,7 +49,10 @@ warning: where clauses are not enforced in type aliases LL | type _TaWhere5 where T: Iterator Into<&'a u8>> = T; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: the clause will not be checked when the type alias is used, and should be removed +help: the clause will not be checked when the type alias is used, and should be removed + | +LL | type _TaWhere5 = T; + | -- warning: where clauses are not enforced in type aliases --> $DIR/type-alias.rs:10:25 @@ -45,7 +60,10 @@ warning: where clauses are not enforced in type aliases LL | type _TaWhere6 where T: Iterator> = T; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: the clause will not be checked when the type alias is used, and should be removed +help: the clause will not be checked when the type alias is used, and should be removed + | +LL | type _TaWhere6 = T; + | -- warning: bounds on generic parameters are not enforced in type aliases --> $DIR/type-alias.rs:12:20 @@ -53,7 +71,10 @@ warning: bounds on generic parameters are not enforced in type aliases LL | type _TaInline1> = T; | ^^^^^^^^^^^^^^^^^^^^ | - = help: the bound will not be checked when the type alias is used, and should be removed +help: the bound will not be checked when the type alias is used, and should be removed + | +LL | type _TaInline1 = T; + | -- warning: bounds on generic parameters are not enforced in type aliases --> $DIR/type-alias.rs:13:20 @@ -61,7 +82,10 @@ warning: bounds on generic parameters are not enforced in type aliases LL | type _TaInline2> = T; | ^^^^^^^^^^^^^^^^^^^^^^^ | - = help: the bound will not be checked when the type alias is used, and should be removed +help: the bound will not be checked when the type alias is used, and should be removed + | +LL | type _TaInline2 = T; + | -- warning: bounds on generic parameters are not enforced in type aliases --> $DIR/type-alias.rs:14:20 @@ -69,7 +93,10 @@ warning: bounds on generic parameters are not enforced in type aliases LL | type _TaInline3> = T; | ^^^^^^^^^^^^^^^^^^^^^^^ | - = help: the bound will not be checked when the type alias is used, and should be removed +help: the bound will not be checked when the type alias is used, and should be removed + | +LL | type _TaInline3 = T; + | -- warning: bounds on generic parameters are not enforced in type aliases --> $DIR/type-alias.rs:15:20 @@ -77,7 +104,10 @@ warning: bounds on generic parameters are not enforced in type aliases LL | type _TaInline4> = T; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: the bound will not be checked when the type alias is used, and should be removed +help: the bound will not be checked when the type alias is used, and should be removed + | +LL | type _TaInline4 = T; + | -- warning: bounds on generic parameters are not enforced in type aliases --> $DIR/type-alias.rs:16:20 @@ -85,7 +115,10 @@ warning: bounds on generic parameters are not enforced in type aliases LL | type _TaInline5 Into<&'a u8>>> = T; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: the bound will not be checked when the type alias is used, and should be removed +help: the bound will not be checked when the type alias is used, and should be removed + | +LL | type _TaInline5 = T; + | -- warning: bounds on generic parameters are not enforced in type aliases --> $DIR/type-alias.rs:17:20 @@ -93,5 +126,8 @@ warning: bounds on generic parameters are not enforced in type aliases LL | type _TaInline6>> = T; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: the bound will not be checked when the type alias is used, and should be removed +help: the bound will not be checked when the type alias is used, and should be removed + | +LL | type _TaInline6 = T; + | -- diff --git a/src/test/ui/privacy/private-in-public-warn.stderr b/src/test/ui/privacy/private-in-public-warn.stderr index 9741f3b6d0d41..40aa47a7246c4 100644 --- a/src/test/ui/privacy/private-in-public-warn.stderr +++ b/src/test/ui/privacy/private-in-public-warn.stderr @@ -340,7 +340,10 @@ LL | pub type Alias = T; | ^^^^^^ | = note: `#[warn(type_alias_bounds)]` on by default - = help: the bound will not be checked when the type alias is used, and should be removed +help: the bound will not be checked when the type alias is used, and should be removed + | +LL | pub type Alias = T; + | -- warning: where clauses are not enforced in type aliases --> $DIR/private-in-public-warn.rs:75:29 @@ -348,7 +351,10 @@ warning: where clauses are not enforced in type aliases LL | pub type Alias where T: PrivTr = T; | ^^^^^^^^^ | - = help: the clause will not be checked when the type alias is used, and should be removed +help: the clause will not be checked when the type alias is used, and should be removed + | +LL | pub type Alias = T; + | -- error: aborting due to 36 previous errors diff --git a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent.stderr b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent.stderr index 0eb0769c57071..cb8bad6d9e74d 100644 --- a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent.stderr +++ b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent.stderr @@ -31,7 +31,10 @@ LL | type Y where i32: Foo = (); | ^^^^^^^^ | = note: `#[warn(type_alias_bounds)]` on by default - = help: the clause will not be checked when the type alias is used, and should be removed +help: the clause will not be checked when the type alias is used, and should be removed + | +LL | type Y = (); + | -- warning: Trait bound i32: Foo does not depend on any type or lifetime parameters --> $DIR/trivial-bounds-inconsistent.rs:22:19 diff --git a/src/test/ui/type/type-alias-bounds.stderr b/src/test/ui/type/type-alias-bounds.stderr index dbb7b92563ab8..c381d30c64f14 100644 --- a/src/test/ui/type/type-alias-bounds.stderr +++ b/src/test/ui/type/type-alias-bounds.stderr @@ -5,7 +5,10 @@ LL | type SVec = Vec; | ^^^^ ^^^^ | = note: `#[warn(type_alias_bounds)]` on by default - = help: the bound will not be checked when the type alias is used, and should be removed +help: the bound will not be checked when the type alias is used, and should be removed + | +LL | type SVec = Vec; + | -- -- warning: where clauses are not enforced in type aliases --> $DIR/type-alias-bounds.rs:10:21 @@ -13,7 +16,10 @@ warning: where clauses are not enforced in type aliases LL | type S2Vec where T: Send = Vec; | ^^^^^^^ | - = help: the clause will not be checked when the type alias is used, and should be removed +help: the clause will not be checked when the type alias is used, and should be removed + | +LL | type S2Vec = Vec; + | -- warning: bounds on generic parameters are not enforced in type aliases --> $DIR/type-alias-bounds.rs:12:19 @@ -21,7 +27,10 @@ warning: bounds on generic parameters are not enforced in type aliases LL | type VVec<'b, 'a: 'b + 'b> = (&'b u32, Vec<&'a i32>); | ^^ ^^ | - = help: the bound will not be checked when the type alias is used, and should be removed +help: the bound will not be checked when the type alias is used, and should be removed + | +LL | type VVec<'b, 'a> = (&'b u32, Vec<&'a i32>); + | -- -- warning: bounds on generic parameters are not enforced in type aliases --> $DIR/type-alias-bounds.rs:14:18 @@ -29,7 +38,10 @@ warning: bounds on generic parameters are not enforced in type aliases LL | type WVec<'b, T: 'b + 'b> = (&'b u32, Vec); | ^^ ^^ | - = help: the bound will not be checked when the type alias is used, and should be removed +help: the bound will not be checked when the type alias is used, and should be removed + | +LL | type WVec<'b, T> = (&'b u32, Vec); + | -- -- warning: where clauses are not enforced in type aliases --> $DIR/type-alias-bounds.rs:16:25 @@ -37,7 +49,10 @@ warning: where clauses are not enforced in type aliases LL | type W2Vec<'b, T> where T: 'b, T: 'b = (&'b u32, Vec); | ^^^^^ ^^^^^ | - = help: the clause will not be checked when the type alias is used, and should be removed +help: the clause will not be checked when the type alias is used, and should be removed + | +LL | type W2Vec<'b, T> = (&'b u32, Vec); + | -- warning: bounds on generic parameters are not enforced in type aliases --> $DIR/type-alias-bounds.rs:47:12 @@ -45,12 +60,15 @@ warning: bounds on generic parameters are not enforced in type aliases LL | type T1 = U::Assoc; | ^^^^^ | - = help: the bound will not be checked when the type alias is used, and should be removed help: use fully disambiguated paths (i.e., `::Assoc`) to refer to associated types in type aliases --> $DIR/type-alias-bounds.rs:47:21 | LL | type T1 = U::Assoc; | ^^^^^^^^ +help: the bound will not be checked when the type alias is used, and should be removed + | +LL | type T1 = U::Assoc; + | -- warning: where clauses are not enforced in type aliases --> $DIR/type-alias-bounds.rs:48:18 @@ -58,12 +76,15 @@ warning: where clauses are not enforced in type aliases LL | type T2 where U: Bound = U::Assoc; | ^^^^^^^^ | - = help: the clause will not be checked when the type alias is used, and should be removed help: use fully disambiguated paths (i.e., `::Assoc`) to refer to associated types in type aliases --> $DIR/type-alias-bounds.rs:48:29 | LL | type T2 where U: Bound = U::Assoc; | ^^^^^^^^ +help: the clause will not be checked when the type alias is used, and should be removed + | +LL | type T2 = U::Assoc; + | -- warning: bounds on generic parameters are not enforced in type aliases --> $DIR/type-alias-bounds.rs:56:12 @@ -71,7 +92,10 @@ warning: bounds on generic parameters are not enforced in type aliases LL | type T5 = ::Assoc; | ^^^^^ | - = help: the bound will not be checked when the type alias is used, and should be removed +help: the bound will not be checked when the type alias is used, and should be removed + | +LL | type T5 = ::Assoc; + | -- warning: bounds on generic parameters are not enforced in type aliases --> $DIR/type-alias-bounds.rs:57:12 @@ -79,5 +103,8 @@ warning: bounds on generic parameters are not enforced in type aliases LL | type T6 = ::std::vec::Vec; | ^^^^^ | - = help: the bound will not be checked when the type alias is used, and should be removed +help: the bound will not be checked when the type alias is used, and should be removed + | +LL | type T6 = ::std::vec::Vec; + | -- From 4479de4b4a375e792127ddcbcb5f91e3b58ce237 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Thu, 10 Oct 2019 17:04:44 +0200 Subject: [PATCH 09/19] ci: extract uploading artifacts into a script --- src/ci/azure-pipelines/steps/run.yml | 44 +++++++++------------------- src/ci/scripts/upload-artifacts.sh | 36 +++++++++++++++++++++++ src/ci/shared.sh | 4 +++ 3 files changed, 54 insertions(+), 30 deletions(-) create mode 100755 src/ci/scripts/upload-artifacts.sh diff --git a/src/ci/azure-pipelines/steps/run.yml b/src/ci/azure-pipelines/steps/run.yml index 01858cca50b1c..c82bc6af738a0 100644 --- a/src/ci/azure-pipelines/steps/run.yml +++ b/src/ci/azure-pipelines/steps/run.yml @@ -201,37 +201,21 @@ steps: condition: and(succeeded(), not(variables.SKIP_JOB)) displayName: Run build -# If we're a deploy builder, use the `aws` command to publish everything to our -# bucket. -- bash: | - set -e - source src/ci/shared.sh - if [ "$AGENT_OS" = "Linux" ]; then - rm -rf obj/build/dist/doc - upload_dir=obj/build/dist - else - rm -rf build/dist/doc - upload_dir=build/dist - fi - ls -la $upload_dir - deploy_dir=rustc-builds - if [ "$DEPLOY_ALT" == "1" ]; then - deploy_dir=rustc-builds-alt - fi - retry aws s3 cp --no-progress --recursive --acl public-read ./$upload_dir s3://$DEPLOY_BUCKET/$deploy_dir/$BUILD_SOURCEVERSION +- bash: src/ci/scripts/upload-artifacts.sh env: AWS_ACCESS_KEY_ID: $(UPLOAD_AWS_ACCESS_KEY_ID) AWS_SECRET_ACCESS_KEY: $(UPLOAD_AWS_SECRET_ACCESS_KEY) - condition: and(succeeded(), not(variables.SKIP_JOB), or(eq(variables.DEPLOY, '1'), eq(variables.DEPLOY_ALT, '1'))) displayName: Upload artifacts - -# Upload CPU usage statistics that we've been gathering this whole time. Always -# execute this step in case we want to inspect failed builds, but don't let -# errors here ever fail the build since this is just informational. -- bash: aws s3 cp --acl public-read cpu-usage.csv s3://$DEPLOY_BUCKET/rustc-builds/$BUILD_SOURCEVERSION/cpu-$CI_JOB_NAME.csv - env: - AWS_ACCESS_KEY_ID: $(UPLOAD_AWS_ACCESS_KEY_ID) - AWS_SECRET_ACCESS_KEY: $(UPLOAD_AWS_SECRET_ACCESS_KEY) - condition: variables['UPLOAD_AWS_SECRET_ACCESS_KEY'] - continueOnError: true - displayName: Upload CPU usage statistics + # Adding a condition on DEPLOY=1 or DEPLOY_ALT=1 is not needed as all deploy + # builders *should* have the AWS credentials available. Still, explicitly + # adding the condition is helpful as this way CI will not silently skip + # deploying artifacts from a dist builder if the variables are misconfigured, + # erroring about invalid credentials instead. + condition: | + and( + succeeded(), not(variables.SKIP_JOB), + or( + variables.UPLOAD_AWS_SECRET_ACCESS_KEY, + eq(variables.DEPLOY, '1'), eq(variables.DEPLOY_ALT, '1') + ) + ) diff --git a/src/ci/scripts/upload-artifacts.sh b/src/ci/scripts/upload-artifacts.sh new file mode 100755 index 0000000000000..2d24fc53a9505 --- /dev/null +++ b/src/ci/scripts/upload-artifacts.sh @@ -0,0 +1,36 @@ +#!/bin/bash +# Upload all the artifacts to our S3 bucket. All the files inside ${upload_dir} +# will be uploaded to the deploy bucket and eventually signed and released in +# static.rust-lang.org. + +set -euo pipefail +IFS=$'\n\t' + +source "$(cd "$(dirname "$0")" && pwd)/../shared.sh" + +upload_dir="$(mktemp -d)" + +# Release tarballs produced by a dist builder. +if [[ "${DEPLOY-0}" = "1" ]] || [[ "${DEPLOY_ALT-0}" = "1" ]]; then + dist_dir=build/dist + if isLinux; then + dist_dir=obj/build/dist + fi + rm -rf "${dist_dir}/doc" + cp -r "${dist_dir}"/* "${upload_dir}" +fi + +# CPU usage statistics. +cp cpu-usage.csv "${upload_dir}/cpu-${CI_JOB_NAME}.csv" + +echo "Files that will be uploaded:" +ls -lah "${upload_dir}" +echo + +deploy_dir="rustc-builds" +if [[ "${DEPLOY_ALT-0}" = "1" ]]; then + deploy_dir="rustc-builds-alt" +fi +deploy_url="s3://${DEPLOY_BUCKET}/${deploy_dir}/$(ciCommit)" + +retry aws s3 cp --no-progress --recursive --acl public-read "${upload_dir}" "${deploy_url}" diff --git a/src/ci/shared.sh b/src/ci/shared.sh index 37e45b5639dc9..718a5379ae558 100644 --- a/src/ci/shared.sh +++ b/src/ci/shared.sh @@ -46,6 +46,10 @@ function getCIBranch { echo "$BUILD_SOURCEBRANCHNAME" } +function ciCommit { + echo "${BUILD_SOURCEVERSION}" +} + function ciCommandAddPath { if [[ $# -ne 1 ]]; then echo "usage: $0 " From 02000505c157350496283c86710d5d314999545a Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Thu, 10 Oct 2019 17:32:50 +0200 Subject: [PATCH 10/19] ci: upload toolstates.json to rust-lang-ci2 Uploading the toolstate data for each commit will help our release tooling understand which components are failing, to possibly skip shipping broken tools to users. --- src/ci/azure-pipelines/auto.yml | 2 ++ src/ci/scripts/upload-artifacts.sh | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/src/ci/azure-pipelines/auto.yml b/src/ci/azure-pipelines/auto.yml index 24b07a1b7c950..651b40cdf297a 100644 --- a/src/ci/azure-pipelines/auto.yml +++ b/src/ci/azure-pipelines/auto.yml @@ -140,6 +140,7 @@ jobs: IMAGE: x86_64-gnu-aux x86_64-gnu-tools: IMAGE: x86_64-gnu-tools + DEPLOY_TOOLSTATES_JSON: toolstates-linux.json x86_64-gnu-debug: IMAGE: x86_64-gnu-debug x86_64-gnu-nopt: @@ -264,6 +265,7 @@ jobs: MSYS_BITS: 64 SCRIPT: src/ci/docker/x86_64-gnu-tools/checktools.sh x.py /tmp/toolstates.json windows RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --save-toolstates=/tmp/toolstates.json + DEPLOY_TOOLSTATES_JSON: toolstates-windows.json # 32/64-bit MinGW builds. # diff --git a/src/ci/scripts/upload-artifacts.sh b/src/ci/scripts/upload-artifacts.sh index 2d24fc53a9505..f060dd28f718c 100755 --- a/src/ci/scripts/upload-artifacts.sh +++ b/src/ci/scripts/upload-artifacts.sh @@ -23,6 +23,11 @@ fi # CPU usage statistics. cp cpu-usage.csv "${upload_dir}/cpu-${CI_JOB_NAME}.csv" +# Toolstate data. +if [[ ! -z "${DEPLOY_TOOLSTATES_JSON+x}" ]]; then + cp /tmp/toolstates.json "${upload_dir}/${DEPLOY_TOOLSTATES_JSON}" +fi + echo "Files that will be uploaded:" ls -lah "${upload_dir}" echo From bdfcde439bcea75d74fe3b181d13332384daf130 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Tue, 29 Oct 2019 10:14:42 +0100 Subject: [PATCH 11/19] Apply suggestions from lzutao Co-Authored-By: lzutao --- src/ci/scripts/upload-artifacts.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ci/scripts/upload-artifacts.sh b/src/ci/scripts/upload-artifacts.sh index f060dd28f718c..625cf378a9be3 100755 --- a/src/ci/scripts/upload-artifacts.sh +++ b/src/ci/scripts/upload-artifacts.sh @@ -11,7 +11,7 @@ source "$(cd "$(dirname "$0")" && pwd)/../shared.sh" upload_dir="$(mktemp -d)" # Release tarballs produced by a dist builder. -if [[ "${DEPLOY-0}" = "1" ]] || [[ "${DEPLOY_ALT-0}" = "1" ]]; then +if [[ "${DEPLOY-0}" -eq "1" ]] || [[ "${DEPLOY_ALT-0}" -eq "1" ]]; then dist_dir=build/dist if isLinux; then dist_dir=obj/build/dist @@ -24,7 +24,7 @@ fi cp cpu-usage.csv "${upload_dir}/cpu-${CI_JOB_NAME}.csv" # Toolstate data. -if [[ ! -z "${DEPLOY_TOOLSTATES_JSON+x}" ]]; then +if [[ -n "${DEPLOY_TOOLSTATES_JSON+x}" ]]; then cp /tmp/toolstates.json "${upload_dir}/${DEPLOY_TOOLSTATES_JSON}" fi @@ -33,7 +33,7 @@ ls -lah "${upload_dir}" echo deploy_dir="rustc-builds" -if [[ "${DEPLOY_ALT-0}" = "1" ]]; then +if [[ "${DEPLOY_ALT-0}" -eq "1" ]]; then deploy_dir="rustc-builds-alt" fi deploy_url="s3://${DEPLOY_BUCKET}/${deploy_dir}/$(ciCommit)" From afbb89ee1d0b8346da5bd445f39ca1638732241b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Mon, 28 Oct 2019 00:00:00 +0000 Subject: [PATCH 12/19] Optimize long-linker-command-line test Replace O(n^3) text matching with inexpensive hash set lookups. On my machine this reduces the total runtime of complete run-make-fulldeps suite from roughly 75 seconds to 45 seconds. --- .../long-linker-command-lines/foo.rs | 77 ++++++++++++------- 1 file changed, 48 insertions(+), 29 deletions(-) diff --git a/src/test/run-make-fulldeps/long-linker-command-lines/foo.rs b/src/test/run-make-fulldeps/long-linker-command-lines/foo.rs index ac42141365e9d..fb76de571d105 100644 --- a/src/test/run-make-fulldeps/long-linker-command-lines/foo.rs +++ b/src/test/run-make-fulldeps/long-linker-command-lines/foo.rs @@ -7,12 +7,43 @@ // Eventually we should see an argument that looks like `@` as we switch from // passing literal arguments to passing everything in the file. +use std::collections::HashSet; use std::env; use std::fs::{self, File}; -use std::io::{BufWriter, Write, Read}; -use std::path::PathBuf; +use std::io::{BufWriter, Write}; +use std::path::{Path, PathBuf}; use std::process::Command; +fn write_test_case(file: &Path, n: usize) -> HashSet { + let mut libs = HashSet::new(); + let mut f = BufWriter::new(File::create(&file).unwrap()); + let mut prefix = String::new(); + for _ in 0..n { + prefix.push_str("foo"); + } + for i in 0..n { + writeln!(f, "#[link(name = \"{}{}\")]", prefix, i).unwrap(); + libs.insert(format!("{}{}", prefix, i)); + } + writeln!(f, "extern {{}}\nfn main() {{}}").unwrap(); + f.into_inner().unwrap(); + + libs +} + +fn read_linker_args(path: &Path) -> String { + let contents = fs::read(path).unwrap(); + if cfg!(target_env = "msvc") { + let mut i = contents.chunks(2).map(|c| { + c[0] as u16 | ((c[1] as u16) << 8) + }); + assert_eq!(i.next(), Some(0xfeff), "Expected UTF-16 BOM"); + String::from_utf16(&i.collect::>()).unwrap() + } else { + String::from_utf8(contents).unwrap() + } +} + fn main() { let tmpdir = PathBuf::from(env::var_os("TMPDIR").unwrap()); let ok = tmpdir.join("ok"); @@ -29,16 +60,7 @@ fn main() { for i in (1..).map(|i| i * 100) { println!("attempt: {}", i); let file = tmpdir.join("bar.rs"); - let mut f = BufWriter::new(File::create(&file).unwrap()); - let mut lib_name = String::new(); - for _ in 0..i { - lib_name.push_str("foo"); - } - for j in 0..i { - writeln!(f, "#[link(name = \"{}{}\")]", lib_name, j).unwrap(); - } - writeln!(f, "extern {{}}\nfn main() {{}}").unwrap(); - f.into_inner().unwrap(); + let mut expected_libs = write_test_case(&file, i); drop(fs::remove_file(&ok)); let output = Command::new(&rustc) @@ -67,25 +89,22 @@ fn main() { continue } - let mut contents = Vec::new(); - File::open(&ok).unwrap().read_to_end(&mut contents).unwrap(); - - for j in 0..i { - let exp = format!("{}{}", lib_name, j); - let exp = if cfg!(target_env = "msvc") { - let mut out = Vec::with_capacity(exp.len() * 2); - for c in exp.encode_utf16() { - // encode in little endian - out.push(c as u8); - out.push((c >> 8) as u8); - } - out - } else { - exp.into_bytes() - }; - assert!(contents.windows(exp.len()).any(|w| w == &exp[..])); + for mut arg in read_linker_args(&ok).lines() { + if arg.starts_with("-l") { + arg = &arg["-l".len()..]; + } + if arg.ends_with(".lib") { + arg = &arg[..arg.len() - ".lib".len()]; + } + expected_libs.remove(arg); } + assert!( + expected_libs.is_empty(), + "expected but missing libraries: {:#?}", + expected_libs, + ); + break } } From c3521fe940324447de6bc54470647aaefe54a6bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 3 Oct 2019 11:41:27 -0700 Subject: [PATCH 13/19] Custom lifetime error for `impl` item doesn't conform to `trait` --- .../error_reporting/nice_region_error/mod.rs | 2 + .../trait_impl_difference.rs | 53 +++++++++++++++++++ .../mismatched_trait_impl-2.rs | 2 +- .../mismatched_trait_impl-2.stderr | 17 ++---- .../mismatched_trait_impl.rs | 2 +- .../mismatched_trait_impl.stderr | 21 ++------ ...ifetime-mismatch-between-trait-and-impl.rs | 12 +++++ ...ime-mismatch-between-trait-and-impl.stderr | 11 ++++ src/test/ui/reject-specialized-drops-8142.rs | 2 +- .../ui/reject-specialized-drops-8142.stderr | 19 ++----- 10 files changed, 93 insertions(+), 48 deletions(-) create mode 100644 src/librustc/infer/error_reporting/nice_region_error/trait_impl_difference.rs create mode 100644 src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.rs create mode 100644 src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr diff --git a/src/librustc/infer/error_reporting/nice_region_error/mod.rs b/src/librustc/infer/error_reporting/nice_region_error/mod.rs index 1edb1c601bf1a..cd003aa8dab70 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/mod.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/mod.rs @@ -12,6 +12,7 @@ mod named_anon_conflict; mod placeholder_error; mod outlives_closure; mod static_impl_trait; +mod trait_impl_difference; mod util; impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { @@ -73,6 +74,7 @@ impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> { .or_else(|| self.try_report_anon_anon_conflict()) .or_else(|| self.try_report_outlives_closure()) .or_else(|| self.try_report_static_impl_trait()) + .or_else(|| self.try_report_impl_not_conforming_to_trait()) } pub fn get_regions(&self) -> (Span, ty::Region<'tcx>, ty::Region<'tcx>) { diff --git a/src/librustc/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/src/librustc/infer/error_reporting/nice_region_error/trait_impl_difference.rs new file mode 100644 index 0000000000000..bd5be89358939 --- /dev/null +++ b/src/librustc/infer/error_reporting/nice_region_error/trait_impl_difference.rs @@ -0,0 +1,53 @@ +//! Error Reporting for `impl` items that do not match the obligations from their `trait`. + +use crate::infer::{ValuePairs, Subtype}; +use crate::infer::error_reporting::nice_region_error::NiceRegionError; +use crate::infer::lexical_region_resolve::RegionResolutionError; +use crate::util::common::ErrorReported; + +impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { + /// Print the error message for lifetime errors when the `impl` doesn't conform to the `trait`. + pub(super) fn try_report_impl_not_conforming_to_trait(&self) -> Option { + if let Some(ref error) = self.error { + if let RegionResolutionError::SubSupConflict( + _, + var_origin, + sub_origin, + _sub, + sup_origin, + _sup, + ) = error.clone() { + match (&sup_origin, &sub_origin) { + (&Subtype(ref sup_trace), &Subtype(ref sub_trace)) => { + if let ( + ValuePairs::Types(sub_expected_found), + ValuePairs::Types(sup_expected_found), + ) = (&sub_trace.values, &sup_trace.values) { + if sup_expected_found == sub_expected_found { + let sp = var_origin.span(); + let mut err = self.tcx().sess.struct_span_err( + sp, + "`impl` item doesn't match `trait` item" + ); + err.note(&format!( + "expected: {:?}\n found: {:?}", + sub_expected_found.expected, + sub_expected_found.found, + )); + err.span_label(sp, &format!( + "found {:?}", + sub_expected_found.found, + )); + // FIXME: recover the `FnPtr`'s `HirId`/`Node` to point to it. + err.emit(); + return Some(ErrorReported); + } + } + } + _ => {} + } + } + } + None + } +} diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.rs b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.rs index d131a944721d0..3c44af7188f81 100644 --- a/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.rs +++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.rs @@ -9,6 +9,6 @@ impl Deref for Struct { unimplemented!(); } } -//~^^^^ ERROR cannot infer an appropriate lifetime for lifetime parameter +//~^^^^ ERROR `impl` item doesn't match `trait` item fn main() {} diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr index c1ec536ef4362..d3228951b2596 100644 --- a/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr +++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr @@ -1,20 +1,11 @@ -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in generic type due to conflicting requirements +error: `impl` item doesn't match `trait` item --> $DIR/mismatched_trait_impl-2.rs:8:5 | LL | fn deref(&self) -> &dyn Trait { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found fn(&Struct) -> &dyn Trait | -note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 8:5... - --> $DIR/mismatched_trait_impl-2.rs:8:5 - | -LL | / fn deref(&self) -> &dyn Trait { -LL | | unimplemented!(); -LL | | } - | |_____^ - = note: ...but the lifetime must also be valid for the static lifetime... - = note: ...so that the method type is compatible with trait: - expected fn(&Struct) -> &(dyn Trait + 'static) - found fn(&Struct) -> &dyn Trait + = note: expected: fn(&Struct) -> &(dyn Trait + 'static) + found: fn(&Struct) -> &dyn Trait error: aborting due to previous error diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.rs b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.rs index f2ba81af9b638..a9b80a7c46fdc 100644 --- a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.rs +++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.rs @@ -6,7 +6,7 @@ trait Get { } impl Get for i32 { - fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { //~ ERROR cannot infer + fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { //~ ERROR `impl` item doesn't match `trait` x //~ ERROR lifetime mismatch } } diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr index 734ca0819e416..ae65125a3dfd8 100644 --- a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr +++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr @@ -1,24 +1,11 @@ -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter 'a in generic type due to conflicting requirements +error: `impl` item doesn't match `trait` item --> $DIR/mismatched_trait_impl.rs:9:5 | LL | fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found fn(&i32, &u32, &u32) -> &u32 | -note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the method body at 9:5... - --> $DIR/mismatched_trait_impl.rs:9:5 - | -LL | / fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { -LL | | x -LL | | } - | |_____^ -note: ...but the lifetime must also be valid for the lifetime `'a` as defined on the method body at 9:32... - --> $DIR/mismatched_trait_impl.rs:9:32 - | -LL | fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { - | ^^ - = note: ...so that the method type is compatible with trait: - expected fn(&i32, &'a u32, &u32) -> &'a u32 - found fn(&i32, &u32, &u32) -> &u32 + = note: expected: fn(&i32, &'a u32, &u32) -> &'a u32 + found: fn(&i32, &u32, &u32) -> &u32 error[E0623]: lifetime mismatch --> $DIR/mismatched_trait_impl.rs:10:9 diff --git a/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.rs b/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.rs new file mode 100644 index 0000000000000..cd285e70bc8f3 --- /dev/null +++ b/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.rs @@ -0,0 +1,12 @@ +trait Foo { + fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32; +} + +impl Foo for () { + fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 { + //~^ ERROR `impl` item doesn't match `trait` item + if x > y { x } else { y } + } +} + +fn main() {} diff --git a/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr b/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr new file mode 100644 index 0000000000000..099e5e97e17e0 --- /dev/null +++ b/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr @@ -0,0 +1,11 @@ +error: `impl` item doesn't match `trait` item + --> $DIR/lifetime-mismatch-between-trait-and-impl.rs:6:5 + | +LL | fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found fn(&i32, &i32) -> &i32 + | + = note: expected: fn(&i32, &'a i32) -> &'a i32 + found: fn(&i32, &i32) -> &i32 + +error: aborting due to previous error + diff --git a/src/test/ui/reject-specialized-drops-8142.rs b/src/test/ui/reject-specialized-drops-8142.rs index f047e16bc0b94..39b959a2206c3 100644 --- a/src/test/ui/reject-specialized-drops-8142.rs +++ b/src/test/ui/reject-specialized-drops-8142.rs @@ -52,6 +52,6 @@ impl Drop for V { fn drop(&mut self) { } } // REJECT //~^ ERROR Implementations of Drop cannot be specialized impl<'lw> Drop for W<'lw,'lw> { fn drop(&mut self) { } } // REJECT -//~^ ERROR cannot infer an appropriate lifetime +//~^ ERROR `impl` item doesn't match `trait` item pub fn main() { } diff --git a/src/test/ui/reject-specialized-drops-8142.stderr b/src/test/ui/reject-specialized-drops-8142.stderr index 609a40163a30c..7aa766dc50341 100644 --- a/src/test/ui/reject-specialized-drops-8142.stderr +++ b/src/test/ui/reject-specialized-drops-8142.stderr @@ -89,25 +89,14 @@ note: Use same sequence of generic type and region parameters that is on the str LL | struct V { x: *const Tva, y: *const Tvb } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'lw` due to conflicting requirements +error: `impl` item doesn't match `trait` item --> $DIR/reject-specialized-drops-8142.rs:54:1 | LL | impl<'lw> Drop for W<'lw,'lw> { fn drop(&mut self) { } } // REJECT - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: first, the lifetime cannot outlive the lifetime `'l1` as defined on the struct at 17:10... - --> $DIR/reject-specialized-drops-8142.rs:17:10 - | -LL | struct W<'l1, 'l2> { x: &'l1 i8, y: &'l2 u8 } - | ^^^ -note: ...but the lifetime must also be valid for the lifetime `'l2` as defined on the struct at 17:15... - --> $DIR/reject-specialized-drops-8142.rs:17:15 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found W<'_, '_> | -LL | struct W<'l1, 'l2> { x: &'l1 i8, y: &'l2 u8 } - | ^^^ - = note: ...so that the types are compatible: - expected W<'l1, 'l2> - found W<'_, '_> + = note: expected: W<'l1, 'l2> + found: W<'_, '_> error: aborting due to 8 previous errors From ef2a8539aa4bdbcd641e51c5a85c7deb27dfae84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 3 Oct 2019 20:14:48 -0700 Subject: [PATCH 14/19] review comments --- .../trait_impl_difference.rs | 27 ++++++++++--------- .../mismatched_trait_impl-2.rs | 2 +- .../mismatched_trait_impl-2.stderr | 2 +- .../mismatched_trait_impl.rs | 2 +- .../mismatched_trait_impl.stderr | 2 +- ...ifetime-mismatch-between-trait-and-impl.rs | 2 +- ...ime-mismatch-between-trait-and-impl.stderr | 2 +- src/test/ui/reject-specialized-drops-8142.rs | 2 +- .../ui/reject-specialized-drops-8142.stderr | 2 +- 9 files changed, 23 insertions(+), 20 deletions(-) diff --git a/src/librustc/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/src/librustc/infer/error_reporting/nice_region_error/trait_impl_difference.rs index bd5be89358939..f546acdb87859 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/trait_impl_difference.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/trait_impl_difference.rs @@ -1,5 +1,7 @@ //! Error Reporting for `impl` items that do not match the obligations from their `trait`. +use syntax_pos::Span; +use crate::ty::Ty; use crate::infer::{ValuePairs, Subtype}; use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::lexical_region_resolve::RegionResolutionError; @@ -25,21 +27,11 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { ) = (&sub_trace.values, &sup_trace.values) { if sup_expected_found == sub_expected_found { let sp = var_origin.span(); - let mut err = self.tcx().sess.struct_span_err( + self.emit_err( sp, - "`impl` item doesn't match `trait` item" - ); - err.note(&format!( - "expected: {:?}\n found: {:?}", sub_expected_found.expected, sub_expected_found.found, - )); - err.span_label(sp, &format!( - "found {:?}", - sub_expected_found.found, - )); - // FIXME: recover the `FnPtr`'s `HirId`/`Node` to point to it. - err.emit(); + ); return Some(ErrorReported); } } @@ -50,4 +42,15 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { } None } + + fn emit_err(&self, sp: Span, expected: Ty<'tcx>, found: Ty<'tcx>) { + let mut err = self.tcx().sess.struct_span_err( + sp, + "`impl` item signature doesn't match `trait` item signature", + ); + err.note(&format!("expected: {:?}\n found: {:?}", expected, found)); + err.span_label(sp, &format!("found {:?}", found)); + // FIXME: recover the `FnPtr`'s `HirId`/`Node` to point to it. + err.emit(); + } } diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.rs b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.rs index 3c44af7188f81..60e1585a51a80 100644 --- a/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.rs +++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.rs @@ -9,6 +9,6 @@ impl Deref for Struct { unimplemented!(); } } -//~^^^^ ERROR `impl` item doesn't match `trait` item +//~^^^^ ERROR `impl` item signature doesn't match `trait` item signature fn main() {} diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr index d3228951b2596..ea88cb14f0118 100644 --- a/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr +++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr @@ -1,4 +1,4 @@ -error: `impl` item doesn't match `trait` item +error: `impl` item signature doesn't match `trait` item signature --> $DIR/mismatched_trait_impl-2.rs:8:5 | LL | fn deref(&self) -> &dyn Trait { diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.rs b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.rs index a9b80a7c46fdc..b9e02e967c126 100644 --- a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.rs +++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.rs @@ -6,7 +6,7 @@ trait Get { } impl Get for i32 { - fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { //~ ERROR `impl` item doesn't match `trait` + fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { //~ ERROR `impl` item signature doesn't match x //~ ERROR lifetime mismatch } } diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr index ae65125a3dfd8..4b0af292bbc24 100644 --- a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr +++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr @@ -1,4 +1,4 @@ -error: `impl` item doesn't match `trait` item +error: `impl` item signature doesn't match `trait` item signature --> $DIR/mismatched_trait_impl.rs:9:5 | LL | fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { diff --git a/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.rs b/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.rs index cd285e70bc8f3..2ce1a0f454651 100644 --- a/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.rs +++ b/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.rs @@ -4,7 +4,7 @@ trait Foo { impl Foo for () { fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 { - //~^ ERROR `impl` item doesn't match `trait` item + //~^ ERROR `impl` item signature doesn't match `trait` item signature if x > y { x } else { y } } } diff --git a/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr b/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr index 099e5e97e17e0..cdb4c16eca35b 100644 --- a/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr +++ b/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr @@ -1,4 +1,4 @@ -error: `impl` item doesn't match `trait` item +error: `impl` item signature doesn't match `trait` item signature --> $DIR/lifetime-mismatch-between-trait-and-impl.rs:6:5 | LL | fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 { diff --git a/src/test/ui/reject-specialized-drops-8142.rs b/src/test/ui/reject-specialized-drops-8142.rs index 39b959a2206c3..621626f3a0d91 100644 --- a/src/test/ui/reject-specialized-drops-8142.rs +++ b/src/test/ui/reject-specialized-drops-8142.rs @@ -52,6 +52,6 @@ impl Drop for V { fn drop(&mut self) { } } // REJECT //~^ ERROR Implementations of Drop cannot be specialized impl<'lw> Drop for W<'lw,'lw> { fn drop(&mut self) { } } // REJECT -//~^ ERROR `impl` item doesn't match `trait` item +//~^ ERROR `impl` item signature doesn't match `trait` item signature pub fn main() { } diff --git a/src/test/ui/reject-specialized-drops-8142.stderr b/src/test/ui/reject-specialized-drops-8142.stderr index 7aa766dc50341..bc7604cdede57 100644 --- a/src/test/ui/reject-specialized-drops-8142.stderr +++ b/src/test/ui/reject-specialized-drops-8142.stderr @@ -89,7 +89,7 @@ note: Use same sequence of generic type and region parameters that is on the str LL | struct V { x: *const Tva, y: *const Tvb } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: `impl` item doesn't match `trait` item +error: `impl` item signature doesn't match `trait` item signature --> $DIR/reject-specialized-drops-8142.rs:54:1 | LL | impl<'lw> Drop for W<'lw,'lw> { fn drop(&mut self) { } } // REJECT From 6998085c030d657d7c8698585409c0fe878d5e7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 15 Oct 2019 10:36:26 -0700 Subject: [PATCH 15/19] Point at the trait item and tweak wording --- .../nice_region_error/trait_impl_difference.rs | 18 +++++++++++++++--- .../mismatched_trait_impl-2.rs | 2 +- .../mismatched_trait_impl-2.stderr | 10 +++++++--- .../mismatched_trait_impl.stderr | 8 +++++--- ...time-mismatch-between-trait-and-impl.stderr | 7 +++++-- .../ui/reject-specialized-drops-8142.stderr | 6 +++--- 6 files changed, 36 insertions(+), 15 deletions(-) diff --git a/src/librustc/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/src/librustc/infer/error_reporting/nice_region_error/trait_impl_difference.rs index f546acdb87859..565ba6b33b8c0 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/trait_impl_difference.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/trait_impl_difference.rs @@ -6,11 +6,13 @@ use crate::infer::{ValuePairs, Subtype}; use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::lexical_region_resolve::RegionResolutionError; use crate::util::common::ErrorReported; +use crate::traits::ObligationCauseCode::CompareImplMethodObligation; impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { /// Print the error message for lifetime errors when the `impl` doesn't conform to the `trait`. pub(super) fn try_report_impl_not_conforming_to_trait(&self) -> Option { if let Some(ref error) = self.error { + debug!("try_report_impl_not_conforming_to_trait {:?}", error); if let RegionResolutionError::SubSupConflict( _, var_origin, @@ -27,10 +29,18 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { ) = (&sub_trace.values, &sup_trace.values) { if sup_expected_found == sub_expected_found { let sp = var_origin.span(); + let impl_sp = if let CompareImplMethodObligation { + trait_item_def_id, .. + } = &sub_trace.cause.code { + Some(self.tcx().def_span(*trait_item_def_id)) + } else { + None + }; self.emit_err( sp, sub_expected_found.expected, sub_expected_found.found, + impl_sp, ); return Some(ErrorReported); } @@ -43,14 +53,16 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { None } - fn emit_err(&self, sp: Span, expected: Ty<'tcx>, found: Ty<'tcx>) { + fn emit_err(&self, sp: Span, expected: Ty<'tcx>, found: Ty<'tcx>, impl_sp: Option) { let mut err = self.tcx().sess.struct_span_err( sp, "`impl` item signature doesn't match `trait` item signature", ); - err.note(&format!("expected: {:?}\n found: {:?}", expected, found)); + err.note(&format!("expected `{:?}`\n found `{:?}`", expected, found)); err.span_label(sp, &format!("found {:?}", found)); - // FIXME: recover the `FnPtr`'s `HirId`/`Node` to point to it. + if let Some(span) = impl_sp { + err.span_label(span, &format!("expected {:?}", expected)); + } err.emit(); } } diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.rs b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.rs index 60e1585a51a80..1b524ec3833e8 100644 --- a/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.rs +++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.rs @@ -6,9 +6,9 @@ struct Struct; impl Deref for Struct { type Target = dyn Trait; fn deref(&self) -> &dyn Trait { + //~^ ERROR `impl` item signature doesn't match `trait` item signature unimplemented!(); } } -//~^^^^ ERROR `impl` item signature doesn't match `trait` item signature fn main() {} diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr index ea88cb14f0118..c1c4ec9ed7b92 100644 --- a/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr +++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr @@ -3,10 +3,14 @@ error: `impl` item signature doesn't match `trait` item signature | LL | fn deref(&self) -> &dyn Trait { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found fn(&Struct) -> &dyn Trait + | + ::: $SRC_DIR/libcore/ops/deref.rs:LL:COL | - = note: expected: fn(&Struct) -> &(dyn Trait + 'static) - found: fn(&Struct) -> &dyn Trait +LL | fn deref(&self) -> &Self::Target; + | --------------------------------- expected fn(&Struct) -> &(dyn Trait + 'static) + | + = note: expected `fn(&Struct) -> &(dyn Trait + 'static)` + found `fn(&Struct) -> &dyn Trait` error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr index 4b0af292bbc24..bc302e91c1c51 100644 --- a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr +++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr @@ -1,11 +1,14 @@ error: `impl` item signature doesn't match `trait` item signature --> $DIR/mismatched_trait_impl.rs:9:5 | +LL | fn foo(&self, x: &'a u32, y: &u32) -> &'a u32; + | ---------------------------------------------- expected fn(&i32, &'a u32, &u32) -> &'a u32 +... LL | fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found fn(&i32, &u32, &u32) -> &u32 | - = note: expected: fn(&i32, &'a u32, &u32) -> &'a u32 - found: fn(&i32, &u32, &u32) -> &u32 + = note: expected `fn(&i32, &'a u32, &u32) -> &'a u32` + found `fn(&i32, &u32, &u32) -> &u32` error[E0623]: lifetime mismatch --> $DIR/mismatched_trait_impl.rs:10:9 @@ -19,4 +22,3 @@ LL | x error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr b/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr index cdb4c16eca35b..d07f305954b6e 100644 --- a/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr +++ b/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr @@ -1,11 +1,14 @@ error: `impl` item signature doesn't match `trait` item signature --> $DIR/lifetime-mismatch-between-trait-and-impl.rs:6:5 | +LL | fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32; + | ------------------------------------------- expected fn(&i32, &'a i32) -> &'a i32 +... LL | fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found fn(&i32, &i32) -> &i32 | - = note: expected: fn(&i32, &'a i32) -> &'a i32 - found: fn(&i32, &i32) -> &i32 + = note: expected `fn(&i32, &'a i32) -> &'a i32` + found `fn(&i32, &i32) -> &i32` error: aborting due to previous error diff --git a/src/test/ui/reject-specialized-drops-8142.stderr b/src/test/ui/reject-specialized-drops-8142.stderr index bc7604cdede57..887edc7299375 100644 --- a/src/test/ui/reject-specialized-drops-8142.stderr +++ b/src/test/ui/reject-specialized-drops-8142.stderr @@ -95,10 +95,10 @@ error: `impl` item signature doesn't match `trait` item signature LL | impl<'lw> Drop for W<'lw,'lw> { fn drop(&mut self) { } } // REJECT | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found W<'_, '_> | - = note: expected: W<'l1, 'l2> - found: W<'_, '_> + = note: expected `W<'l1, 'l2>` + found `W<'_, '_>` error: aborting due to 8 previous errors -Some errors have detailed explanations: E0308, E0366, E0367, E0495. +Some errors have detailed explanations: E0308, E0366, E0367. For more information about an error, try `rustc --explain E0308`. From 9ae0c1d7e9dc18a06b1280561e539175da189b71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 15 Oct 2019 10:47:48 -0700 Subject: [PATCH 16/19] Make error apply only to impl/trait mismatch --- .../trait_impl_difference.rs | 21 ++++++------------- src/test/ui/reject-specialized-drops-8142.rs | 2 +- .../ui/reject-specialized-drops-8142.stderr | 21 ++++++++++++++----- 3 files changed, 23 insertions(+), 21 deletions(-) diff --git a/src/librustc/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/src/librustc/infer/error_reporting/nice_region_error/trait_impl_difference.rs index 565ba6b33b8c0..0194300c50721 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/trait_impl_difference.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/trait_impl_difference.rs @@ -26,21 +26,14 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { if let ( ValuePairs::Types(sub_expected_found), ValuePairs::Types(sup_expected_found), - ) = (&sub_trace.values, &sup_trace.values) { + CompareImplMethodObligation { trait_item_def_id, .. }, + ) = (&sub_trace.values, &sup_trace.values, &sub_trace.cause.code) { if sup_expected_found == sub_expected_found { - let sp = var_origin.span(); - let impl_sp = if let CompareImplMethodObligation { - trait_item_def_id, .. - } = &sub_trace.cause.code { - Some(self.tcx().def_span(*trait_item_def_id)) - } else { - None - }; self.emit_err( - sp, + var_origin.span(), sub_expected_found.expected, sub_expected_found.found, - impl_sp, + self.tcx().def_span(*trait_item_def_id), ); return Some(ErrorReported); } @@ -53,16 +46,14 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { None } - fn emit_err(&self, sp: Span, expected: Ty<'tcx>, found: Ty<'tcx>, impl_sp: Option) { + fn emit_err(&self, sp: Span, expected: Ty<'tcx>, found: Ty<'tcx>, impl_sp: Span) { let mut err = self.tcx().sess.struct_span_err( sp, "`impl` item signature doesn't match `trait` item signature", ); err.note(&format!("expected `{:?}`\n found `{:?}`", expected, found)); err.span_label(sp, &format!("found {:?}", found)); - if let Some(span) = impl_sp { - err.span_label(span, &format!("expected {:?}", expected)); - } + err.span_label(impl_sp, &format!("expected {:?}", expected)); err.emit(); } } diff --git a/src/test/ui/reject-specialized-drops-8142.rs b/src/test/ui/reject-specialized-drops-8142.rs index 621626f3a0d91..b3cb83f94e053 100644 --- a/src/test/ui/reject-specialized-drops-8142.rs +++ b/src/test/ui/reject-specialized-drops-8142.rs @@ -52,6 +52,6 @@ impl Drop for V { fn drop(&mut self) { } } // REJECT //~^ ERROR Implementations of Drop cannot be specialized impl<'lw> Drop for W<'lw,'lw> { fn drop(&mut self) { } } // REJECT -//~^ ERROR `impl` item signature doesn't match `trait` item signature +//~^ ERROR cannot infer an appropriate lifetime for lifetime parameter `'lw` pub fn main() { } diff --git a/src/test/ui/reject-specialized-drops-8142.stderr b/src/test/ui/reject-specialized-drops-8142.stderr index 887edc7299375..609a40163a30c 100644 --- a/src/test/ui/reject-specialized-drops-8142.stderr +++ b/src/test/ui/reject-specialized-drops-8142.stderr @@ -89,16 +89,27 @@ note: Use same sequence of generic type and region parameters that is on the str LL | struct V { x: *const Tva, y: *const Tvb } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: `impl` item signature doesn't match `trait` item signature +error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'lw` due to conflicting requirements --> $DIR/reject-specialized-drops-8142.rs:54:1 | LL | impl<'lw> Drop for W<'lw,'lw> { fn drop(&mut self) { } } // REJECT - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found W<'_, '_> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first, the lifetime cannot outlive the lifetime `'l1` as defined on the struct at 17:10... + --> $DIR/reject-specialized-drops-8142.rs:17:10 + | +LL | struct W<'l1, 'l2> { x: &'l1 i8, y: &'l2 u8 } + | ^^^ +note: ...but the lifetime must also be valid for the lifetime `'l2` as defined on the struct at 17:15... + --> $DIR/reject-specialized-drops-8142.rs:17:15 | - = note: expected `W<'l1, 'l2>` - found `W<'_, '_>` +LL | struct W<'l1, 'l2> { x: &'l1 i8, y: &'l2 u8 } + | ^^^ + = note: ...so that the types are compatible: + expected W<'l1, 'l2> + found W<'_, '_> error: aborting due to 8 previous errors -Some errors have detailed explanations: E0308, E0366, E0367. +Some errors have detailed explanations: E0308, E0366, E0367, E0495. For more information about an error, try `rustc --explain E0308`. From a3b86879a09d71755025770038ccc6675cb10c06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 15 Oct 2019 10:57:52 -0700 Subject: [PATCH 17/19] Fix NLL test --- .../mismatched_trait_impl.nll.stderr | 25 ++++++------------- 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.nll.stderr b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.nll.stderr index b5287f32a5045..c245d78ae828f 100644 --- a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.nll.stderr +++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.nll.stderr @@ -1,25 +1,14 @@ -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter 'a in generic type due to conflicting requirements +error: `impl` item signature doesn't match `trait` item signature --> $DIR/mismatched_trait_impl.rs:9:5 | +LL | fn foo(&self, x: &'a u32, y: &u32) -> &'a u32; + | ---------------------------------------------- expected fn(&i32, &'a u32, &u32) -> &'a u32 +... LL | fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found fn(&i32, &u32, &u32) -> &u32 | -note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the method body at 9:5... - --> $DIR/mismatched_trait_impl.rs:9:5 - | -LL | / fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { -LL | | x -LL | | } - | |_____^ -note: ...but the lifetime must also be valid for the lifetime `'a` as defined on the method body at 9:32... - --> $DIR/mismatched_trait_impl.rs:9:32 - | -LL | fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { - | ^^ - = note: ...so that the method type is compatible with trait: - expected fn(&i32, &'a u32, &u32) -> &'a u32 - found fn(&i32, &u32, &u32) -> &u32 + = note: expected `fn(&i32, &'a u32, &u32) -> &'a u32` + found `fn(&i32, &u32, &u32) -> &u32` error: aborting due to previous error -For more information about this error, try `rustc --explain E0495`. From 213fd1f37f272e352ceb7dcdaddcd90b1da54d61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 29 Oct 2019 10:19:40 -0700 Subject: [PATCH 18/19] Silence crate external span error in x86 platforms This causes issues in at least `dist-i586-gnu-i586-i686-musl`, possibly others. --- src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.rs | 2 ++ src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.rs b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.rs index 1b524ec3833e8..eca9a67fcb387 100644 --- a/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.rs +++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.rs @@ -1,3 +1,5 @@ +// ignore-x86 +// ^ due to stderr output differences use std::ops::Deref; trait Trait {} diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr index c1c4ec9ed7b92..d3862e3d4df60 100644 --- a/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr +++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr @@ -1,5 +1,5 @@ error: `impl` item signature doesn't match `trait` item signature - --> $DIR/mismatched_trait_impl-2.rs:8:5 + --> $DIR/mismatched_trait_impl-2.rs:10:5 | LL | fn deref(&self) -> &dyn Trait { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found fn(&Struct) -> &dyn Trait From 08ca2360c4e817acab717dfb7e5a93d5af35cc06 Mon Sep 17 00:00:00 2001 From: jack-t Date: Fri, 4 Oct 2019 01:56:57 -0400 Subject: [PATCH 19/19] Add lint for unnecessary parens around types --- .../nice_region_error/find_anon_type.rs | 2 +- .../owning_ref/mod.rs | 8 ++--- src/librustc_lint/unused.rs | 19 ++++++++++++ src/librustc_mir/borrow_check/prefixes.rs | 2 +- src/libstd/collections/hash/map.rs | 6 ++-- src/test/ui/alignment-gep-tup-like-1.rs | 2 +- src/test/ui/as-precedence.rs | 1 + src/test/ui/close-over-big-then-small-data.rs | 2 +- .../closure-to-fn-coercion.rs | 2 +- src/test/ui/lint/lint-unnecessary-parens.rs | 12 ++++++++ .../ui/lint/lint-unnecessary-parens.stderr | 30 +++++++++++-------- .../single-use-lifetime/zero-uses-in-fn.fixed | 2 +- .../ui/single-use-lifetime/zero-uses-in-fn.rs | 2 +- .../zero-uses-in-fn.stderr | 2 +- 14 files changed, 65 insertions(+), 27 deletions(-) diff --git a/src/librustc/infer/error_reporting/nice_region_error/find_anon_type.rs b/src/librustc/infer/error_reporting/nice_region_error/find_anon_type.rs index 9c362a5e20791..f4751e591bf3c 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/find_anon_type.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/find_anon_type.rs @@ -62,7 +62,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { &self, arg: &'tcx hir::Ty, br: &ty::BoundRegion, - ) -> Option<(&'tcx hir::Ty)> { + ) -> Option<&'tcx hir::Ty> { let mut nested_visitor = FindNestedTypeVisitor { tcx: self.tcx(), bound_region: *br, diff --git a/src/librustc_data_structures/owning_ref/mod.rs b/src/librustc_data_structures/owning_ref/mod.rs index b835b1706b85f..0213eb4f2a2a4 100644 --- a/src/librustc_data_structures/owning_ref/mod.rs +++ b/src/librustc_data_structures/owning_ref/mod.rs @@ -1046,14 +1046,14 @@ unsafe impl CloneStableAddress for OwningRef where O: CloneStableAddress {} unsafe impl Send for OwningRef - where O: Send, for<'a> (&'a T): Send {} + where O: Send, for<'a> &'a T: Send {} unsafe impl Sync for OwningRef - where O: Sync, for<'a> (&'a T): Sync {} + where O: Sync, for<'a> &'a T: Sync {} unsafe impl Send for OwningRefMut - where O: Send, for<'a> (&'a mut T): Send {} + where O: Send, for<'a> &'a mut T: Send {} unsafe impl Sync for OwningRefMut - where O: Sync, for<'a> (&'a mut T): Sync {} + where O: Sync, for<'a> &'a mut T: Sync {} impl Debug for dyn Erased { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 3b3995832cb4c..7a168baacaf81 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -603,6 +603,25 @@ impl EarlyLintPass for UnusedParens { fn check_arm(&mut self, cx: &EarlyContext<'_>, arm: &ast::Arm) { self.check_unused_parens_pat(cx, &arm.pat, false, false); } + + fn check_ty(&mut self, cx: &EarlyContext<'_>, ty: &ast::Ty) { + if let &ast::TyKind::Paren(ref r) = &ty.kind { + match &r.kind { + &ast::TyKind::TraitObject(..) => {} + &ast::TyKind::ImplTrait(_, ref bounds) if bounds.len() > 1 => {} + _ => { + let pattern_text = if let Ok(snippet) = cx.sess().source_map() + .span_to_snippet(ty.span) { + snippet + } else { + pprust::ty_to_string(ty) + }; + + Self::remove_outer_parens(cx, ty.span, &pattern_text, "type", (false, false)); + } + } + } + } } declare_lint! { diff --git a/src/librustc_mir/borrow_check/prefixes.rs b/src/librustc_mir/borrow_check/prefixes.rs index a46a1cc5647a9..1be1fcef61b6e 100644 --- a/src/librustc_mir/borrow_check/prefixes.rs +++ b/src/librustc_mir/borrow_check/prefixes.rs @@ -29,7 +29,7 @@ pub(super) struct Prefixes<'cx, 'tcx> { body: &'cx Body<'tcx>, tcx: TyCtxt<'tcx>, kind: PrefixSet, - next: Option<(PlaceRef<'cx, 'tcx>)>, + next: Option>, } #[derive(Copy, Clone, PartialEq, Eq, Debug)] diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index ff50051ef5040..941c81eaff264 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -1818,7 +1818,7 @@ impl<'a, K, V> Iterator for Keys<'a, K, V> { type Item = &'a K; #[inline] - fn next(&mut self) -> Option<(&'a K)> { + fn next(&mut self) -> Option<&'a K> { self.inner.next().map(|(k, _)| k) } #[inline] @@ -1841,7 +1841,7 @@ impl<'a, K, V> Iterator for Values<'a, K, V> { type Item = &'a V; #[inline] - fn next(&mut self) -> Option<(&'a V)> { + fn next(&mut self) -> Option<&'a V> { self.inner.next().map(|(_, v)| v) } #[inline] @@ -1864,7 +1864,7 @@ impl<'a, K, V> Iterator for ValuesMut<'a, K, V> { type Item = &'a mut V; #[inline] - fn next(&mut self) -> Option<(&'a mut V)> { + fn next(&mut self) -> Option<&'a mut V> { self.inner.next().map(|(_, v)| v) } #[inline] diff --git a/src/test/ui/alignment-gep-tup-like-1.rs b/src/test/ui/alignment-gep-tup-like-1.rs index c51c56b089926..adbd05ed8c175 100644 --- a/src/test/ui/alignment-gep-tup-like-1.rs +++ b/src/test/ui/alignment-gep-tup-like-1.rs @@ -28,7 +28,7 @@ fn f(a: A, b: u16) -> Box+'static> { box Invoker { a: a, b: b, - } as (Box+'static>) + } as Box+'static> } pub fn main() { diff --git a/src/test/ui/as-precedence.rs b/src/test/ui/as-precedence.rs index a9f6fceb08ff0..feb0cb30ccacc 100644 --- a/src/test/ui/as-precedence.rs +++ b/src/test/ui/as-precedence.rs @@ -1,5 +1,6 @@ // run-pass +#[allow(unused_parens)] fn main() { assert_eq!(3 as usize * 3, 9); assert_eq!(3 as (usize) * 3, 9); diff --git a/src/test/ui/close-over-big-then-small-data.rs b/src/test/ui/close-over-big-then-small-data.rs index 40e5f500df4a8..4d6edf4ecb0f3 100644 --- a/src/test/ui/close-over-big-then-small-data.rs +++ b/src/test/ui/close-over-big-then-small-data.rs @@ -30,7 +30,7 @@ fn f(a: A, b: u16) -> Box+'static> { box Invoker { a: a, b: b, - } as (Box+'static>) + } as Box+'static> } pub fn main() { diff --git a/src/test/ui/functions-closures/closure-to-fn-coercion.rs b/src/test/ui/functions-closures/closure-to-fn-coercion.rs index 4f43c2bb53847..87ba488b5aef2 100644 --- a/src/test/ui/functions-closures/closure-to-fn-coercion.rs +++ b/src/test/ui/functions-closures/closure-to-fn-coercion.rs @@ -10,7 +10,7 @@ const BAR: [fn(&mut u32); 5] = [ |v: &mut u32| *v += 3, |v: &mut u32| *v += 4, ]; -fn func_specific() -> (fn() -> u32) { +fn func_specific() -> fn() -> u32 { || return 42 } diff --git a/src/test/ui/lint/lint-unnecessary-parens.rs b/src/test/ui/lint/lint-unnecessary-parens.rs index 811bc87eb0e2e..9f42b855a870d 100644 --- a/src/test/ui/lint/lint-unnecessary-parens.rs +++ b/src/test/ui/lint/lint-unnecessary-parens.rs @@ -13,6 +13,18 @@ fn bar(y: bool) -> X { return (X { y }); //~ ERROR unnecessary parentheses around `return` value } +fn unused_parens_around_return_type() -> (u32) { //~ ERROR unnecessary parentheses around type + panic!() +} + +trait Trait { + fn test(&self); +} + +fn passes_unused_parens_lint() -> &'static (dyn Trait) { + panic!() +} + fn main() { foo(); bar((true)); //~ ERROR unnecessary parentheses around function argument diff --git a/src/test/ui/lint/lint-unnecessary-parens.stderr b/src/test/ui/lint/lint-unnecessary-parens.stderr index 83b247a4a6053..adc1069b64d62 100644 --- a/src/test/ui/lint/lint-unnecessary-parens.stderr +++ b/src/test/ui/lint/lint-unnecessary-parens.stderr @@ -16,26 +16,32 @@ error: unnecessary parentheses around `return` value LL | return (X { y }); | ^^^^^^^^^ help: remove these parentheses +error: unnecessary parentheses around type + --> $DIR/lint-unnecessary-parens.rs:16:42 + | +LL | fn unused_parens_around_return_type() -> (u32) { + | ^^^^^ help: remove these parentheses + error: unnecessary parentheses around function argument - --> $DIR/lint-unnecessary-parens.rs:18:9 + --> $DIR/lint-unnecessary-parens.rs:30:9 | LL | bar((true)); | ^^^^^^ help: remove these parentheses error: unnecessary parentheses around `if` condition - --> $DIR/lint-unnecessary-parens.rs:20:8 + --> $DIR/lint-unnecessary-parens.rs:32:8 | LL | if (true) {} | ^^^^^^ help: remove these parentheses error: unnecessary parentheses around `while` condition - --> $DIR/lint-unnecessary-parens.rs:21:11 + --> $DIR/lint-unnecessary-parens.rs:33:11 | LL | while (true) {} | ^^^^^^ help: remove these parentheses warning: denote infinite loops with `loop { ... }` - --> $DIR/lint-unnecessary-parens.rs:21:5 + --> $DIR/lint-unnecessary-parens.rs:33:5 | LL | while (true) {} | ^^^^^^^^^^^^ help: use `loop` @@ -43,46 +49,46 @@ LL | while (true) {} = note: `#[warn(while_true)]` on by default error: unnecessary parentheses around `match` head expression - --> $DIR/lint-unnecessary-parens.rs:23:11 + --> $DIR/lint-unnecessary-parens.rs:35:11 | LL | match (true) { | ^^^^^^ help: remove these parentheses error: unnecessary parentheses around `let` head expression - --> $DIR/lint-unnecessary-parens.rs:26:16 + --> $DIR/lint-unnecessary-parens.rs:38:16 | LL | if let 1 = (1) {} | ^^^ help: remove these parentheses error: unnecessary parentheses around `let` head expression - --> $DIR/lint-unnecessary-parens.rs:27:19 + --> $DIR/lint-unnecessary-parens.rs:39:19 | LL | while let 1 = (2) {} | ^^^ help: remove these parentheses error: unnecessary parentheses around method argument - --> $DIR/lint-unnecessary-parens.rs:41:24 + --> $DIR/lint-unnecessary-parens.rs:53:24 | LL | X { y: false }.foo((true)); | ^^^^^^ help: remove these parentheses error: unnecessary parentheses around assigned value - --> $DIR/lint-unnecessary-parens.rs:43:18 + --> $DIR/lint-unnecessary-parens.rs:55:18 | LL | let mut _a = (0); | ^^^ help: remove these parentheses error: unnecessary parentheses around assigned value - --> $DIR/lint-unnecessary-parens.rs:44:10 + --> $DIR/lint-unnecessary-parens.rs:56:10 | LL | _a = (0); | ^^^ help: remove these parentheses error: unnecessary parentheses around assigned value - --> $DIR/lint-unnecessary-parens.rs:45:11 + --> $DIR/lint-unnecessary-parens.rs:57:11 | LL | _a += (1); | ^^^ help: remove these parentheses -error: aborting due to 12 previous errors +error: aborting due to 13 previous errors diff --git a/src/test/ui/single-use-lifetime/zero-uses-in-fn.fixed b/src/test/ui/single-use-lifetime/zero-uses-in-fn.fixed index 89607af260a52..0f26a975a370f 100644 --- a/src/test/ui/single-use-lifetime/zero-uses-in-fn.fixed +++ b/src/test/ui/single-use-lifetime/zero-uses-in-fn.fixed @@ -15,7 +15,7 @@ fn october<'b, T>(s: &'b T) -> &'b T { s } -fn november<'a>(s: &'a str) -> (&'a str) { +fn november<'a>(s: &'a str) -> &'a str { //~^ ERROR lifetime parameter `'b` never used //~| HELP elide the unused lifetime s diff --git a/src/test/ui/single-use-lifetime/zero-uses-in-fn.rs b/src/test/ui/single-use-lifetime/zero-uses-in-fn.rs index be0bdb9b62851..7f9504fe5a90a 100644 --- a/src/test/ui/single-use-lifetime/zero-uses-in-fn.rs +++ b/src/test/ui/single-use-lifetime/zero-uses-in-fn.rs @@ -15,7 +15,7 @@ fn october<'a, 'b, T>(s: &'b T) -> &'b T { s } -fn november<'a, 'b>(s: &'a str) -> (&'a str) { +fn november<'a, 'b>(s: &'a str) -> &'a str { //~^ ERROR lifetime parameter `'b` never used //~| HELP elide the unused lifetime s diff --git a/src/test/ui/single-use-lifetime/zero-uses-in-fn.stderr b/src/test/ui/single-use-lifetime/zero-uses-in-fn.stderr index 2ccba796d4229..b9c3bd89748ff 100644 --- a/src/test/ui/single-use-lifetime/zero-uses-in-fn.stderr +++ b/src/test/ui/single-use-lifetime/zero-uses-in-fn.stderr @@ -21,7 +21,7 @@ LL | fn october<'a, 'b, T>(s: &'b T) -> &'b T { error: lifetime parameter `'b` never used --> $DIR/zero-uses-in-fn.rs:18:17 | -LL | fn november<'a, 'b>(s: &'a str) -> (&'a str) { +LL | fn november<'a, 'b>(s: &'a str) -> &'a str { | --^^ | | | help: elide the unused lifetime