diff --git a/Cargo.lock b/Cargo.lock index 5826a1dbbd949..0e0ea739ed6d5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3412,17 +3412,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" @@ -3809,17 +3776,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" @@ -4175,10 +4131,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/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..9cd208a1d137c 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)); @@ -157,13 +157,18 @@ 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 } /// 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 +213,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")); @@ -280,31 +270,108 @@ 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)); + } +} + +/// Copies sanitizer runtime libraries into target libdir. +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 target_deps; + } + + let llvm_config: PathBuf = builder.ensure(native::Llvm { + target: compiler.host, + }); + if builder.config.dry_run { + 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(*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); + 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()); + } + + target_deps.push(dst); } + + target_deps } -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)); +/// 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/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/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 e76604e45bdeb..962d0a183d819 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/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/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/azure-pipelines/steps/run.yml b/src/ci/azure-pipelines/steps/run.yml index b8e32cf2cdfe3..cef2d235602f1 100644 --- a/src/ci/azure-pipelines/steps/run.yml +++ b/src/ci/azure-pipelines/steps/run.yml @@ -183,37 +183,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..625cf378a9be3 --- /dev/null +++ b/src/ci/scripts/upload-artifacts.sh @@ -0,0 +1,41 @@ +#!/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}" -eq "1" ]] || [[ "${DEPLOY_ALT-0}" -eq "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" + +# Toolstate data. +if [[ -n "${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 + +deploy_dir="rustc-builds" +if [[ "${DEPLOY_ALT-0}" -eq "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 " 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 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/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/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..0194300c50721 --- /dev/null +++ b/src/librustc/infer/error_reporting/nice_region_error/trait_impl_difference.rs @@ -0,0 +1,59 @@ +//! 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; +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, + 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), + CompareImplMethodObligation { trait_item_def_id, .. }, + ) = (&sub_trace.values, &sup_trace.values, &sub_trace.cause.code) { + if sup_expected_found == sub_expected_found { + self.emit_err( + var_origin.span(), + sub_expected_found.expected, + sub_expected_found.found, + self.tcx().def_span(*trait_item_def_id), + ); + return Some(ErrorReported); + } + } + } + _ => {} + } + } + } + None + } + + 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)); + err.span_label(impl_sp, &format!("expected {:?}", expected)); + err.emit(); + } +} diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index d13b21bb7722b..22eeb7a73f340 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -646,10 +646,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/session/mod.rs b/src/librustc/session/mod.rs index 8bf4765111d36..0365d6428fe92 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/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"), 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_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index a2b50ea8e2bf7..0a490078d0f38 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -523,6 +523,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(); @@ -726,6 +727,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. /// @@ -1392,11 +1436,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) => { @@ -1436,45 +1475,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_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index ee4ec7fb41eac..72668e76efd75 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -719,7 +719,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), @@ -755,9 +754,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 dd75883f97deb..b74af1ed1037e 100644 --- a/src/librustc_codegen_ssa/lib.rs +++ b/src/librustc_codegen_ssa/lib.rs @@ -131,7 +131,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_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/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/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 9a826de4b6eaf..af43030d0f2ae 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -598,6 +598,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_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_metadata/creader.rs b/src/librustc_metadata/creader.rs index 234a5395047c6..27a4817e5f9e9 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/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 f6498f4eaa891..961380af3c708 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -574,7 +574,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/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/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'] } diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 6b0225a1b443a..de2f12c9f33ef 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/libsyntax/feature_gate/active.rs b/src/libsyntax/feature_gate/active.rs index 22638a1376c72..0a84b9cfbfca9 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/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 } } 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..2f485ae4fa4c3 100644 --- a/src/test/run-make-fulldeps/sanitizer-leak/Makefile +++ b/src/test/run-make-fulldeps/sanitizer-leak/Makefile @@ -3,9 +3,7 @@ # 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_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 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/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/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/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`. 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/in-band-lifetimes/mismatched_trait_impl-2.rs b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.rs index d131a944721d0..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 {} @@ -6,9 +8,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 cannot infer an appropriate lifetime for lifetime parameter 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..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,21 +1,16 @@ -error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in generic type due to conflicting requirements - --> $DIR/mismatched_trait_impl-2.rs:8:5 +error: `impl` item signature doesn't match `trait` item signature + --> $DIR/mismatched_trait_impl-2.rs:10:5 | LL | fn deref(&self) -> &dyn Trait { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found fn(&Struct) -> &dyn Trait + | + ::: $SRC_DIR/libcore/ops/deref.rs:LL:COL | -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) -> &Self::Target; + | --------------------------------- expected fn(&Struct) -> &(dyn Trait + 'static) | -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 -For more information about this error, try `rustc --explain E0495`. 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`. 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..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 cannot infer + 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 734ca0819e416..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,24 +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[E0623]: lifetime mismatch --> $DIR/mismatched_trait_impl.rs:10:9 @@ -32,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.rs b/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.rs new file mode 100644 index 0000000000000..2ce1a0f454651 --- /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 signature doesn't match `trait` item signature + 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..d07f305954b6e --- /dev/null +++ b/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr @@ -0,0 +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` + +error: aborting due to previous error + 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/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/reject-specialized-drops-8142.rs b/src/test/ui/reject-specialized-drops-8142.rs index f047e16bc0b94..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 cannot infer an appropriate lifetime +//~^ ERROR cannot infer an appropriate lifetime for lifetime parameter `'lw` pub fn main() { } 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 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; + | --