diff options
144 files changed, 1916 insertions, 901 deletions
diff --git a/Cargo.lock b/Cargo.lock index 07a6c53c9c8..1af0442dde7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3435,7 +3435,27 @@ dependencies = [ name = "rustc_codegen_llvm" version = "0.0.0" dependencies = [ + "bitflags", + "flate2", + "libc", + "log", + "rustc", + "rustc-demangle", + "rustc_codegen_ssa", + "rustc_codegen_utils", + "rustc_data_structures", + "rustc_errors", + "rustc_feature", + "rustc_fs_util", + "rustc_incremental", + "rustc_index", "rustc_llvm", + "rustc_session", + "rustc_target", + "smallvec 0.6.10", + "syntax", + "syntax_expand", + "syntax_pos", ] [[package]] @@ -3597,6 +3617,7 @@ dependencies = [ "once_cell", "rustc", "rustc-rayon", + "rustc_codegen_llvm", "rustc_codegen_ssa", "rustc_codegen_utils", "rustc_data_structures", @@ -3651,6 +3672,7 @@ version = "0.0.0" dependencies = [ "build_helper", "cc", + "libc", ] [[package]] @@ -3924,6 +3946,8 @@ dependencies = [ "minifier", "pulldown-cmark 0.5.3", "rustc-rayon", + "serde", + "serde_json", "tempfile", ] diff --git a/config.toml.example b/config.toml.example index e832570ed98..5152a6c9885 100644 --- a/config.toml.example +++ b/config.toml.example @@ -379,9 +379,6 @@ # and currently the only standard option supported is `"llvm"` #codegen-backends = ["llvm"] -# This is the name of the directory in which codegen backends will get installed -#codegen-backends-dir = "codegen-backends" - # Indicates whether LLD will be compiled and made available in the sysroot for # rustc to execute. #lld = false diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index fc1e1cf2b1d..8b0ad169cfc 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -339,7 +339,6 @@ impl<'a> Builder<'a> { Kind::Build => describe!( compile::Std, compile::Rustc, - compile::CodegenBackend, compile::StartupObjects, tool::BuildManifest, tool::Rustbook, @@ -364,7 +363,6 @@ impl<'a> Builder<'a> { Kind::Check | Kind::Clippy | Kind::Fix => describe!( check::Std, check::Rustc, - check::CodegenBackend, check::Rustdoc ), Kind::Test => describe!( @@ -632,11 +630,6 @@ impl<'a> Builder<'a> { self.ensure(Libdir { compiler, target }) } - pub fn sysroot_codegen_backends(&self, compiler: Compiler) -> PathBuf { - self.sysroot_libdir(compiler, compiler.host) - .with_file_name(self.config.rust_codegen_backends_dir.clone()) - } - /// Returns the compiler's libdir where it stores the dynamic libraries that /// it itself links against. /// @@ -707,15 +700,6 @@ impl<'a> Builder<'a> { } } - /// Gets the paths to all of the compiler's codegen backends. - fn codegen_backends(&self, compiler: Compiler) -> impl Iterator<Item = PathBuf> { - fs::read_dir(self.sysroot_codegen_backends(compiler)) - .into_iter() - .flatten() - .filter_map(Result::ok) - .map(|entry| entry.path()) - } - pub fn rustdoc(&self, compiler: Compiler) -> PathBuf { self.ensure(tool::Rustdoc { compiler }) } @@ -759,12 +743,6 @@ impl<'a> Builder<'a> { let mut cargo = Command::new(&self.initial_cargo); let out_dir = self.stage_out(compiler, mode); - // Codegen backends are not yet tracked by -Zbinary-dep-depinfo, - // so we need to explicitly clear out if they've been updated. - for backend in self.codegen_backends(compiler) { - self.clear_if_dirty(&out_dir, &backend); - } - if cmd == "doc" || cmd == "rustdoc" { let my_out = match mode { // This is the intended out directory for compiler documentation. diff --git a/src/bootstrap/builder/tests.rs b/src/bootstrap/builder/tests.rs index 2bb90fdb04e..b9d97fb8b76 100644 --- a/src/bootstrap/builder/tests.rs +++ b/src/bootstrap/builder/tests.rs @@ -363,6 +363,10 @@ fn dist_with_same_targets_and_hosts() { compiler: Compiler { host: a, stage: 1 }, target: b, }, + compile::Std { + compiler: Compiler { host: a, stage: 2 }, + target: b, + }, ] ); assert_eq!( diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index df1c7257584..f5c427d870e 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -1,11 +1,10 @@ //! Implementation of compiling the compiler and standard library, in "check"-based modes. -use crate::compile::{run_cargo, std_cargo, rustc_cargo, rustc_cargo_env, - add_to_sysroot}; +use crate::compile::{run_cargo, std_cargo, rustc_cargo, add_to_sysroot}; use crate::builder::{RunConfig, Builder, Kind, ShouldRun, Step}; use crate::tool::{prepare_tool_cargo, SourceType}; use crate::{Compiler, Mode}; -use crate::cache::{INTERNER, Interned}; +use crate::cache::Interned; use std::path::PathBuf; #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] @@ -97,7 +96,7 @@ impl Step for Rustc { let mut cargo = builder.cargo(compiler, Mode::Rustc, target, cargo_subcommand(builder.kind)); - rustc_cargo(builder, &mut cargo); + rustc_cargo(builder, &mut cargo, target); builder.info(&format!("Checking compiler artifacts ({} -> {})", &compiler.host, target)); run_cargo(builder, @@ -114,55 +113,6 @@ impl Step for Rustc { } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub struct CodegenBackend { - pub target: Interned<String>, - pub backend: Interned<String>, -} - -impl Step for CodegenBackend { - type Output = (); - const ONLY_HOSTS: bool = true; - const DEFAULT: bool = true; - - fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.all_krates("rustc_codegen_llvm") - } - - fn make_run(run: RunConfig<'_>) { - let backend = run.builder.config.rust_codegen_backends.get(0); - let backend = backend.cloned().unwrap_or_else(|| { - INTERNER.intern_str("llvm") - }); - run.builder.ensure(CodegenBackend { - target: run.target, - backend, - }); - } - - fn run(self, builder: &Builder<'_>) { - let compiler = builder.compiler(0, builder.config.build); - let target = self.target; - let backend = self.backend; - - builder.ensure(Rustc { target }); - - let mut cargo = builder.cargo(compiler, Mode::Codegen, target, - cargo_subcommand(builder.kind)); - cargo.arg("--manifest-path").arg(builder.src.join("src/librustc_codegen_llvm/Cargo.toml")); - rustc_cargo_env(builder, &mut cargo); - - // We won't build LLVM if it's not available, as it shouldn't affect `check`. - - run_cargo(builder, - cargo, - args(builder.kind), - &codegen_backend_stamp(builder, compiler, target, backend), - vec![], - true); - } -} - -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct Rustdoc { pub target: Interned<String>, } @@ -231,16 +181,6 @@ pub fn librustc_stamp( builder.cargo_out(compiler, Mode::Rustc, target).join(".librustc-check.stamp") } -/// Cargo's output path for librustc_codegen_llvm in a given stage, compiled by a particular -/// compiler for the specified target and backend. -fn codegen_backend_stamp(builder: &Builder<'_>, - compiler: Compiler, - target: Interned<String>, - backend: Interned<String>) -> PathBuf { - builder.cargo_out(compiler, Mode::Codegen, target) - .join(format!(".librustc_codegen_llvm-{}-check.stamp", backend)) -} - /// Cargo's output path for rustdoc in a given stage, compiled by a particular /// compiler for the specified target. pub fn rustdoc_stamp( diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index f686dfe71b9..baf9aabed00 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -27,7 +27,7 @@ use crate::{Compiler, Mode, GitRepo}; use crate::native; use crate::cache::{INTERNER, Interned}; -use crate::builder::{Step, RunConfig, ShouldRun, Builder}; +use crate::builder::{Step, RunConfig, ShouldRun, Builder, Kind}; #[derive(Debug, PartialOrd, Ord, Copy, Clone, PartialEq, Eq, Hash)] pub struct Std { @@ -445,7 +445,7 @@ impl Step for Rustc { }); let mut cargo = builder.cargo(compiler, Mode::Rustc, target, "build"); - rustc_cargo(builder, &mut cargo); + rustc_cargo(builder, &mut cargo, target); builder.info(&format!("Building stage{} compiler artifacts ({} -> {})", compiler.stage, &compiler.host, target)); @@ -456,6 +456,44 @@ impl Step for Rustc { vec![], false); + // We used to build librustc_codegen_llvm as a separate step, + // which produced a dylib that the compiler would dlopen() at runtime. + // This meant that we only needed to make sure that libLLVM.so was + // installed by the time we went to run a tool using it - since + // librustc_codegen_llvm was effectively a standalone artifact, + // other crates were completely oblivious to its dependency + // on `libLLVM.so` during build time. + // + // However, librustc_codegen_llvm is now built as an ordinary + // crate during the same step as the rest of the compiler crates. + // This means that any crates depending on it will see the fact + // that it uses `libLLVM.so` as a native library, and will + // cause us to pass `-llibLLVM.so` to the linker when we link + // a binary. + // + // For `rustc` itself, this works out fine. + // During the `Assemble` step, we call `dist::maybe_install_llvm_dylib` + // to copy libLLVM.so into the `stage` directory. We then link + // the compiler binary, which will find `libLLVM.so` in the correct place. + // + // However, this is insufficient for tools that are build against stage0 + // (e.g. stage1 rustdoc). Since `Assemble` for stage0 doesn't actually do anything, + // we won't have `libLLVM.so` in the stage0 sysroot. In the past, this wasn't + // a problem - we would copy the tool binary into its correct stage directory + // (e.g. stage1 for a stage1 rustdoc built against a stage0 compiler). + // Since libLLVM.so wasn't resolved until runtime, it was fine for it to + // not exist while we were building it. + // + // To ensure that we can still build stage1 tools against a stage0 compiler, + // we explicitly copy libLLVM.so into the stage0 sysroot when building + // the stage0 compiler. This ensures that tools built against stage0 + // will see libLLVM.so at build time, making the linker happy. + if compiler.stage == 0 { + builder.info(&format!("Installing libLLVM.so to stage 0 ({})", compiler.host)); + let sysroot = builder.sysroot(compiler); + dist::maybe_install_llvm_dylib(builder, compiler.host, &sysroot); + } + builder.ensure(RustcLink { compiler: builder.compiler(compiler.stage, builder.config.build), target_compiler: compiler, @@ -464,21 +502,20 @@ impl Step for Rustc { } } -pub fn rustc_cargo(builder: &Builder<'_>, cargo: &mut Cargo) { +pub fn rustc_cargo(builder: &Builder<'_>, cargo: &mut Cargo, target: Interned<String>) { cargo.arg("--features").arg(builder.rustc_features()) .arg("--manifest-path") .arg(builder.src.join("src/rustc/Cargo.toml")); - rustc_cargo_env(builder, cargo); + rustc_cargo_env(builder, cargo, target); } -pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo) { +pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: Interned<String>) { // Set some configuration variables picked up by build scripts and // the compiler alike cargo.env("CFG_RELEASE", builder.rust_release()) .env("CFG_RELEASE_CHANNEL", &builder.config.channel) .env("CFG_VERSION", builder.rust_version()) - .env("CFG_PREFIX", builder.config.prefix.clone().unwrap_or_default()) - .env("CFG_CODEGEN_BACKENDS_DIR", &builder.config.rust_codegen_backends_dir); + .env("CFG_PREFIX", builder.config.prefix.clone().unwrap_or_default()); let libdir_relative = builder.config.libdir_relative().unwrap_or(Path::new("lib")); cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative); @@ -501,6 +538,49 @@ pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo) { if builder.config.rust_verify_llvm_ir { cargo.env("RUSTC_VERIFY_LLVM_IR", "1"); } + + // Pass down configuration from the LLVM build into the build of + // librustc_llvm and librustc_codegen_llvm. + // + // Note that this is disabled if LLVM itself is disabled or we're in a check + // build, where if we're in a check build there's no need to build all of + // LLVM and such. + if builder.config.llvm_enabled() && builder.kind != Kind::Check { + if builder.is_rust_llvm(target) { + cargo.env("LLVM_RUSTLLVM", "1"); + } + let llvm_config = builder.ensure(native::Llvm { target }); + cargo.env("LLVM_CONFIG", &llvm_config); + let target_config = builder.config.target_config.get(&target); + if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) { + cargo.env("CFG_LLVM_ROOT", s); + } + // Some LLVM linker flags (-L and -l) may be needed to link librustc_llvm. + if let Some(ref s) = builder.config.llvm_ldflags { + cargo.env("LLVM_LINKER_FLAGS", s); + } + // Building with a static libstdc++ is only supported on linux right now, + // not for MSVC or macOS + if builder.config.llvm_static_stdcpp && + !target.contains("freebsd") && + !target.contains("windows") && + !target.contains("apple") { + let file = compiler_file(builder, + builder.cxx(target).unwrap(), + target, + "libstdc++.a"); + cargo.env("LLVM_STATIC_STDCPP", file); + } + if builder.config.llvm_link_shared || builder.config.llvm_thin_lto { + cargo.env("LLVM_LINK_SHARED", "1"); + } + if builder.config.llvm_use_libcxx { + cargo.env("LLVM_USE_LIBCXX", "1"); + } + if builder.config.llvm_optimize && !builder.config.llvm_release_debuginfo { + cargo.env("LLVM_NDEBUG", "1"); + } + } } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] @@ -537,215 +617,6 @@ impl Step for RustcLink { } } -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub struct CodegenBackend { - pub compiler: Compiler, - pub target: Interned<String>, - pub backend: Interned<String>, -} - -impl Step for CodegenBackend { - type Output = (); - const ONLY_HOSTS: bool = true; - const DEFAULT: bool = true; - - fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.all_krates("rustc_codegen_llvm") - } - - fn make_run(run: RunConfig<'_>) { - let backend = run.builder.config.rust_codegen_backends.get(0); - let backend = backend.cloned().unwrap_or_else(|| { - INTERNER.intern_str("llvm") - }); - run.builder.ensure(CodegenBackend { - compiler: run.builder.compiler(run.builder.top_stage, run.host), - target: run.target, - backend, - }); - } - - fn run(self, builder: &Builder<'_>) { - let compiler = self.compiler; - let target = self.target; - let backend = self.backend; - - builder.ensure(Rustc { compiler, target }); - - if builder.config.keep_stage.contains(&compiler.stage) { - builder.info("Warning: Using a potentially old codegen backend. \ - This may not behave well."); - // Codegen backends are linked separately from this step today, so we don't do - // anything here. - return; - } - - let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target); - if compiler_to_use != compiler { - builder.ensure(CodegenBackend { - compiler: compiler_to_use, - target, - backend, - }); - return; - } - - let out_dir = builder.cargo_out(compiler, Mode::Codegen, target); - - let mut cargo = builder.cargo(compiler, Mode::Codegen, target, "build"); - cargo.arg("--manifest-path") - .arg(builder.src.join("src/librustc_codegen_llvm/Cargo.toml")); - rustc_cargo_env(builder, &mut cargo); - - let features = build_codegen_backend(&builder, &mut cargo, &compiler, target, backend); - cargo.arg("--features").arg(features); - - let tmp_stamp = out_dir.join(".tmp.stamp"); - - let files = run_cargo(builder, cargo, vec![], &tmp_stamp, vec![], false); - if builder.config.dry_run { - return; - } - let mut files = files.into_iter() - .filter(|f| { - let filename = f.file_name().unwrap().to_str().unwrap(); - is_dylib(filename) && filename.contains("rustc_codegen_llvm-") - }); - let codegen_backend = match files.next() { - Some(f) => f, - None => panic!("no dylibs built for codegen backend?"), - }; - if let Some(f) = files.next() { - panic!("codegen backend built two dylibs:\n{}\n{}", - codegen_backend.display(), - f.display()); - } - let stamp = codegen_backend_stamp(builder, compiler, target, backend); - let codegen_backend = codegen_backend.to_str().unwrap(); - t!(fs::write(&stamp, &codegen_backend)); - } -} - -pub fn build_codegen_backend(builder: &Builder<'_>, - cargo: &mut Cargo, - compiler: &Compiler, - target: Interned<String>, - backend: Interned<String>) -> String { - match &*backend { - "llvm" => { - // Build LLVM for our target. This will implicitly build the - // host LLVM if necessary. - let llvm_config = builder.ensure(native::Llvm { - target, - }); - - builder.info(&format!("Building stage{} codegen artifacts ({} -> {}, {})", - compiler.stage, &compiler.host, target, backend)); - - // Pass down configuration from the LLVM build into the build of - // librustc_llvm and librustc_codegen_llvm. - if builder.is_rust_llvm(target) { - cargo.env("LLVM_RUSTLLVM", "1"); - } - - cargo.env("LLVM_CONFIG", &llvm_config); - let target_config = builder.config.target_config.get(&target); - if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) { - cargo.env("CFG_LLVM_ROOT", s); - } - // Some LLVM linker flags (-L and -l) may be needed to link librustc_llvm. - if let Some(ref s) = builder.config.llvm_ldflags { - cargo.env("LLVM_LINKER_FLAGS", s); - } - // Building with a static libstdc++ is only supported on linux and mingw right now, - // not for MSVC or macOS - if builder.config.llvm_static_stdcpp && - !target.contains("freebsd") && - !target.contains("msvc") && - !target.contains("apple") { - let file = compiler_file(builder, - builder.cxx(target).unwrap(), - target, - "libstdc++.a"); - cargo.env("LLVM_STATIC_STDCPP", file); - } - if builder.config.llvm_link_shared || builder.config.llvm_thin_lto { - cargo.env("LLVM_LINK_SHARED", "1"); - } - if builder.config.llvm_use_libcxx { - cargo.env("LLVM_USE_LIBCXX", "1"); - } - if builder.config.llvm_optimize && !builder.config.llvm_release_debuginfo { - cargo.env("LLVM_NDEBUG", "1"); - } - } - _ => panic!("unknown backend: {}", backend), - } - String::new() -} - -/// Creates the `codegen-backends` folder for a compiler that's about to be -/// assembled as a complete compiler. -/// -/// This will take the codegen artifacts produced by `compiler` and link them -/// into an appropriate location for `target_compiler` to be a functional -/// compiler. -fn copy_codegen_backends_to_sysroot(builder: &Builder<'_>, - compiler: Compiler, - target_compiler: Compiler) { - let target = target_compiler.host; - - // Note that this step is different than all the other `*Link` steps in - // that it's not assembling a bunch of libraries but rather is primarily - // moving the codegen backend into place. The codegen backend of rustc is - // not linked into the main compiler by default but is rather dynamically - // selected at runtime for inclusion. - // - // Here we're looking for the output dylib of the `CodegenBackend` step and - // we're copying that into the `codegen-backends` folder. - let dst = builder.sysroot_codegen_backends(target_compiler); - t!(fs::create_dir_all(&dst)); - - if builder.config.dry_run { - return; - } - - for backend in builder.config.rust_codegen_backends.iter() { - let stamp = codegen_backend_stamp(builder, compiler, target, *backend); - let dylib = t!(fs::read_to_string(&stamp)); - let file = Path::new(&dylib); - let filename = file.file_name().unwrap().to_str().unwrap(); - // change `librustc_codegen_llvm-xxxxxx.so` to `librustc_codegen_llvm-llvm.so` - let target_filename = { - let dash = filename.find('-').unwrap(); - let dot = filename.find('.').unwrap(); - format!("{}-{}{}", - &filename[..dash], - backend, - &filename[dot..]) - }; - builder.copy(&file, &dst.join(target_filename)); - } -} - -fn copy_lld_to_sysroot(builder: &Builder<'_>, - target_compiler: Compiler, - lld_install_root: &Path) { - let target = target_compiler.host; - - let dst = builder.sysroot_libdir(target_compiler, target) - .parent() - .unwrap() - .join("bin"); - t!(fs::create_dir_all(&dst)); - - let src_exe = exe("lld", &target); - let dst_exe = exe("rust-lld", &target); - // we prepend this bin directory to the user PATH when linking Rust binaries. To - // avoid shadowing the system LLD we rename the LLD we provide to `rust-lld`. - builder.copy(&lld_install_root.join("bin").join(&src_exe), &dst.join(&dst_exe)); -} - /// Cargo's output path for the standard library in a given stage, compiled /// by a particular compiler for the specified target. pub fn libstd_stamp( @@ -766,16 +637,6 @@ pub fn librustc_stamp( builder.cargo_out(compiler, Mode::Rustc, target).join(".librustc.stamp") } -/// Cargo's output path for librustc_codegen_llvm in a given stage, compiled by a particular -/// compiler for the specified target and backend. -fn codegen_backend_stamp(builder: &Builder<'_>, - compiler: Compiler, - target: Interned<String>, - backend: Interned<String>) -> PathBuf { - builder.cargo_out(compiler, Mode::Codegen, target) - .join(format!(".librustc_codegen_llvm-{}.stamp", backend)) -} - pub fn compiler_file( builder: &Builder<'_>, compiler: &Path, @@ -879,13 +740,6 @@ impl Step for Assemble { compiler: build_compiler, target: target_compiler.host, }); - for &backend in builder.config.rust_codegen_backends.iter() { - builder.ensure(CodegenBackend { - compiler: build_compiler, - target: target_compiler.host, - backend, - }); - } let lld_install = if builder.config.lld_enabled { Some(builder.ensure(native::Lld { @@ -911,13 +765,19 @@ impl Step for Assemble { } } - copy_codegen_backends_to_sysroot(builder, - build_compiler, - target_compiler); + let libdir = builder.sysroot_libdir(target_compiler, target_compiler.host); if let Some(lld_install) = lld_install { - copy_lld_to_sysroot(builder, target_compiler, &lld_install); + let src_exe = exe("lld", &target_compiler.host); + let dst_exe = exe("rust-lld", &target_compiler.host); + // we prepend this bin directory to the user PATH when linking Rust binaries. To + // avoid shadowing the system LLD we rename the LLD we provide to `rust-lld`. + let dst = libdir.parent().unwrap().join("bin"); + t!(fs::create_dir_all(&dst)); + builder.copy(&lld_install.join("bin").join(&src_exe), &dst.join(&dst_exe)); } + // Ensure that `libLLVM.so` ends up in the newly build compiler directory, + // so that it can be found when the newly built `rustc` is run. dist::maybe_install_llvm_dylib(builder, target_compiler.host, &sysroot); // Link the compiler binary itself into place diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 0c03b95c7b2..5f2ef01bd5c 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -105,7 +105,6 @@ pub struct Config { pub rust_optimize_tests: bool, pub rust_dist_src: bool, pub rust_codegen_backends: Vec<Interned<String>>, - pub rust_codegen_backends_dir: String, pub rust_verify_llvm_ir: bool, pub rust_remap_debuginfo: bool, @@ -316,7 +315,6 @@ struct Rust { dist_src: Option<bool>, save_toolstates: Option<String>, codegen_backends: Option<Vec<String>>, - codegen_backends_dir: Option<String>, lld: Option<bool>, llvm_tools: Option<bool>, lldb: Option<bool>, @@ -372,7 +370,6 @@ impl Config { config.ignore_git = false; config.rust_dist_src = true; config.rust_codegen_backends = vec![INTERNER.intern_str("llvm")]; - config.rust_codegen_backends_dir = "codegen-backends".to_owned(); config.deny_warnings = true; config.missing_tools = false; @@ -575,8 +572,6 @@ impl Config { .collect(); } - set(&mut config.rust_codegen_backends_dir, rust.codegen_backends_dir.clone()); - config.rust_codegen_units = rust.codegen_units.map(threads_from_config); config.rust_codegen_units_std = rust.codegen_units_std.map(threads_from_config); } diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index d0c9e0dbaf4..02533944fc2 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -498,16 +498,6 @@ impl Step for Rustc { } } - // Copy over the codegen backends - let backends_src = builder.sysroot_codegen_backends(compiler); - let backends_rel = backends_src.strip_prefix(&src).unwrap() - .strip_prefix(builder.sysroot_libdir_relative(compiler)).unwrap(); - // Don't use custom libdir here because ^lib/ will be resolved again with installer - let backends_dst = image.join("lib").join(&backends_rel); - - t!(fs::create_dir_all(&backends_dst)); - builder.cp_r(&backends_src, &backends_dst); - // Copy libLLVM.so to the lib dir as well, if needed. While not // technically needed by rustc itself it's needed by lots of other // components like the llvm tools and LLD. LLD is included below and @@ -2134,6 +2124,10 @@ impl Step for HashSign { // Maybe add libLLVM.so to the lib-dir. It will only have been built if // LLVM tools are linked dynamically. +// +// We add this to both the libdir of the rustc binary itself (for it to load at +// runtime) and also to the target directory so it can find it at link-time. +// // Note: This function does no yet support Windows but we also don't support // linking LLVM tools dynamically on Windows yet. pub fn maybe_install_llvm_dylib(builder: &Builder<'_>, @@ -2142,13 +2136,19 @@ pub fn maybe_install_llvm_dylib(builder: &Builder<'_>, let src_libdir = builder .llvm_out(target) .join("lib"); - let dst_libdir = sysroot.join("lib/rustlib").join(&*target).join("lib"); - t!(fs::create_dir_all(&dst_libdir)); + let dst_libdir1 = sysroot.join("lib/rustlib").join(&*target).join("lib"); + let dst_libdir2 = sysroot.join(builder.sysroot_libdir_relative(Compiler { + stage: 1, + host: target, + })); + t!(fs::create_dir_all(&dst_libdir1)); + t!(fs::create_dir_all(&dst_libdir2)); if target.contains("apple-darwin") { let llvm_dylib_path = src_libdir.join("libLLVM.dylib"); if llvm_dylib_path.exists() { - builder.install(&llvm_dylib_path, &dst_libdir, 0o644); + builder.install(&llvm_dylib_path, &dst_libdir1, 0o644); + builder.install(&llvm_dylib_path, &dst_libdir2, 0o644); } return } @@ -2164,7 +2164,8 @@ pub fn maybe_install_llvm_dylib(builder: &Builder<'_>, }); - builder.install(&llvm_dylib_path, &dst_libdir, 0o644); + builder.install(&llvm_dylib_path, &dst_libdir1, 0o644); + builder.install(&llvm_dylib_path, &dst_libdir2, 0o644); } } diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 4ee8cd2485c..608cee0a80b 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -433,7 +433,7 @@ impl Step for Std { builder.info(&format!("Documenting stage{} std ({})", stage, target)); let out = builder.doc_out(target); t!(fs::create_dir_all(&out)); - let compiler = builder.compiler_for(stage, builder.config.build, target); + let compiler = builder.compiler(stage, builder.config.build); builder.ensure(compile::Std { compiler, target }); let out_dir = builder.stage_out(compiler, Mode::Std) @@ -541,7 +541,7 @@ impl Step for Rustc { // Build cargo command. let mut cargo = builder.cargo(compiler, Mode::Rustc, target, "doc"); cargo.env("RUSTDOCFLAGS", "--document-private-items --passes strip-hidden"); - compile::rustc_cargo(builder, &mut cargo); + compile::rustc_cargo(builder, &mut cargo, target); // Only include compiler crates, no dependencies of those, such as `libc`. cargo.arg("--no-deps"); diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 7f7e29108a8..080bef6853a 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -500,6 +500,9 @@ impl Build { if self.config.jemalloc { features.push_str("jemalloc"); } + if self.config.llvm_enabled() { + features.push_str(" llvm"); + } features } diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index a858ed42bad..f3b2a73d3c5 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1773,7 +1773,7 @@ impl Step for Crate { } Mode::Rustc => { builder.ensure(compile::Rustc { compiler, target }); - compile::rustc_cargo(builder, &mut cargo); + compile::rustc_cargo(builder, &mut cargo, target); } _ => panic!("can only test libraries"), }; diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index ebd3f010077..913613653a6 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -144,11 +144,23 @@ impl<T: Clone> Clone for VecDeque<T> { #[stable(feature = "rust1", since = "1.0.0")] unsafe impl<#[may_dangle] T> Drop for VecDeque<T> { fn drop(&mut self) { + /// Runs the destructor for all items in the slice when it gets dropped (normally or + /// during unwinding). + struct Dropper<'a, T>(&'a mut [T]); + + impl<'a, T> Drop for Dropper<'a, T> { + fn drop(&mut self) { + unsafe { + ptr::drop_in_place(self.0); + } + } + } + let (front, back) = self.as_mut_slices(); unsafe { + let _back_dropper = Dropper(back); // use drop for [T] ptr::drop_in_place(front); - ptr::drop_in_place(back); } // RawVec handles deallocation } diff --git a/src/liballoc/tests/vec_deque.rs b/src/liballoc/tests/vec_deque.rs index ebcc8320171..1ab3694a3ca 100644 --- a/src/liballoc/tests/vec_deque.rs +++ b/src/liballoc/tests/vec_deque.rs @@ -2,6 +2,7 @@ use std::collections::TryReserveError::*; use std::collections::{vec_deque::Drain, VecDeque}; use std::fmt::Debug; use std::mem::size_of; +use std::panic::catch_unwind; use std::{isize, usize}; use crate::hash; @@ -710,6 +711,39 @@ fn test_drop_clear() { } #[test] +fn test_drop_panic() { + static mut DROPS: i32 = 0; + + struct D(bool); + + impl Drop for D { + fn drop(&mut self) { + unsafe { + DROPS += 1; + } + + if self.0 { + panic!("panic in `drop`"); + } + } + } + + let mut q = VecDeque::new(); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_front(D(false)); + q.push_front(D(false)); + q.push_front(D(true)); + + catch_unwind(move || drop(q)).ok(); + + assert_eq!(unsafe { DROPS }, 8); +} + +#[test] fn test_reserve_grow() { // test growth path A // [T o o H] -> [T o o H . . . . ] diff --git a/src/libcore/convert/mod.rs b/src/libcore/convert/mod.rs index 27d78b55a75..cdd994d5fc7 100644 --- a/src/libcore/convert/mod.rs +++ b/src/libcore/convert/mod.rs @@ -292,7 +292,7 @@ pub trait Into<T>: Sized { /// [`Into`]. /// /// One should always prefer implementing `From` over [`Into`] -/// because implementing `From` automatically provides one with a implementation of [`Into`] +/// because implementing `From` automatically provides one with an implementation of [`Into`] /// thanks to the blanket implementation in the standard library. /// /// Only implement [`Into`] if a conversion to a type outside the current crate is required. diff --git a/src/libcore/mem/mod.rs b/src/libcore/mem/mod.rs index c50a8ad6000..00b32ad0b73 100644 --- a/src/libcore/mem/mod.rs +++ b/src/libcore/mem/mod.rs @@ -513,7 +513,9 @@ pub unsafe fn zeroed<T>() -> T { /// **This function is deprecated.** Use [`MaybeUninit<T>`] instead. /// /// The reason for deprecation is that the function basically cannot be used -/// correctly: [the Rust compiler assumes][inv] that values are properly initialized. +/// correctly: it has the same effect as [`MaybeUninit::uninit().assume_init()`][uninit]. +/// As the [`assume_init` documentation][assume_init] explains, +/// [the Rust compiler assumes][inv] that values are properly initialized. /// As a consequence, calling e.g. `mem::uninitialized::<bool>()` causes immediate /// undefined behavior for returning a `bool` that is not definitely either `true` /// or `false`. Worse, truly uninitialized memory like what gets returned here @@ -524,6 +526,8 @@ pub unsafe fn zeroed<T>() -> T { /// until they are, it is advisable to avoid them.) /// /// [`MaybeUninit<T>`]: union.MaybeUninit.html +/// [uninit]: union.MaybeUninit.html#method.uninit +/// [assume_init]: union.MaybeUninit.html#method.assume_init /// [inv]: union.MaybeUninit.html#initialization-invariant #[inline] #[rustc_deprecated(since = "1.39.0", reason = "use `mem::MaybeUninit` instead")] diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 58c1498faa9..c9d57706d55 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -70,6 +70,7 @@ use std::{cmp, fmt}; mod note; mod need_type_info; +pub use need_type_info::TypeAnnotationNeeded; pub mod nice_region_error; diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs index 32eecdf01a3..8878683f3a7 100644 --- a/src/librustc/infer/error_reporting/need_type_info.rs +++ b/src/librustc/infer/error_reporting/need_type_info.rs @@ -1,4 +1,4 @@ -use crate::hir::def::Namespace; +use crate::hir::def::{DefKind, Namespace}; use crate::hir::{self, Body, FunctionRetTy, Expr, ExprKind, HirId, Local, Pat}; use crate::hir::intravisit::{self, Visitor, NestedVisitorMap}; use crate::infer::InferCtxt; @@ -6,8 +6,10 @@ use crate::infer::type_variable::TypeVariableOriginKind; use crate::ty::{self, Ty, Infer, TyVar}; use crate::ty::print::Print; use syntax::source_map::DesugaringKind; +use syntax::symbol::kw; use syntax_pos::Span; use errors::{Applicability, DiagnosticBuilder}; +use std::borrow::Cow; use rustc_error_codes::*; @@ -19,6 +21,7 @@ struct FindLocalByTypeVisitor<'a, 'tcx> { found_arg_pattern: Option<&'tcx Pat>, found_ty: Option<Ty<'tcx>>, found_closure: Option<&'tcx ExprKind>, + found_method_call: Option<&'tcx Expr>, } impl<'a, 'tcx> FindLocalByTypeVisitor<'a, 'tcx> { @@ -35,6 +38,7 @@ impl<'a, 'tcx> FindLocalByTypeVisitor<'a, 'tcx> { found_arg_pattern: None, found_ty: None, found_closure: None, + found_method_call: None, } } @@ -93,11 +97,12 @@ impl<'a, 'tcx> Visitor<'tcx> for FindLocalByTypeVisitor<'a, 'tcx> { } fn visit_expr(&mut self, expr: &'tcx Expr) { - if let (ExprKind::Closure(_, _fn_decl, _id, _sp, _), Some(_)) = ( - &expr.kind, - self.node_matches_type(expr.hir_id), - ) { - self.found_closure = Some(&expr.kind); + if self.node_matches_type(expr.hir_id).is_some() { + match expr.kind { + ExprKind::Closure(..) => self.found_closure = Some(&expr.kind), + ExprKind::MethodCall(..) => self.found_method_call = Some(&expr), + _ => {} + } } intravisit::walk_expr(self, expr); } @@ -109,6 +114,7 @@ fn closure_return_type_suggestion( err: &mut DiagnosticBuilder<'_>, output: &FunctionRetTy, body: &Body, + descr: &str, name: &str, ret: &str, ) { @@ -132,7 +138,7 @@ fn closure_return_type_suggestion( suggestion, Applicability::HasPlaceholders, ); - err.span_label(span, InferCtxt::missing_type_msg(&name)); + err.span_label(span, InferCtxt::missing_type_msg(&name, &descr)); } /// Given a closure signature, return a `String` containing a list of all its argument types. @@ -147,17 +153,42 @@ fn closure_args(fn_sig: &ty::PolyFnSig<'_>) -> String { .unwrap_or_default() } +pub enum TypeAnnotationNeeded { + E0282, + E0283, + E0284, +} + +impl Into<errors::DiagnosticId> for TypeAnnotationNeeded { + fn into(self) -> errors::DiagnosticId { + syntax::diagnostic_used!(E0282); + syntax::diagnostic_used!(E0283); + syntax::diagnostic_used!(E0284); + errors::DiagnosticId::Error(match self { + Self::E0282 => "E0282".to_string(), + Self::E0283 => "E0283".to_string(), + Self::E0284 => "E0284".to_string(), + }) + } +} + impl<'a, 'tcx> InferCtxt<'a, 'tcx> { pub fn extract_type_name( &self, ty: Ty<'tcx>, highlight: Option<ty::print::RegionHighlightMode>, - ) -> (String, Option<Span>) { + ) -> (String, Option<Span>, Cow<'static, str>) { if let ty::Infer(ty::TyVar(ty_vid)) = ty.kind { let ty_vars = self.type_variables.borrow(); let var_origin = ty_vars.var_origin(ty_vid); if let TypeVariableOriginKind::TypeParameterDefinition(name) = var_origin.kind { - return (name.to_string(), Some(var_origin.span)); + if name != kw::SelfUpper { + return ( + name.to_string(), + Some(var_origin.span), + "type parameter".into(), + ); + } } } @@ -167,7 +198,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { printer.region_highlight_mode = highlight; } let _ = ty.print(printer); - (s, None) + (s, None, ty.prefix_string()) } pub fn need_type_info_err( @@ -175,9 +206,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { body_id: Option<hir::BodyId>, span: Span, ty: Ty<'tcx>, + error_code: TypeAnnotationNeeded, ) -> DiagnosticBuilder<'tcx> { let ty = self.resolve_vars_if_possible(&ty); - let (name, name_sp) = self.extract_type_name(&ty, None); + let (name, name_sp, descr) = self.extract_type_name(&ty, None); let mut local_visitor = FindLocalByTypeVisitor::new(&self, ty, &self.tcx.hir()); let ty_to_string = |ty: Ty<'tcx>| -> String { @@ -185,8 +217,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS); let ty_vars = self.type_variables.borrow(); let getter = move |ty_vid| { - if let TypeVariableOriginKind::TypeParameterDefinition(name) = - ty_vars.var_origin(ty_vid).kind { + let var_origin = ty_vars.var_origin(ty_vid); + if let TypeVariableOriginKind::TypeParameterDefinition(name) = var_origin.kind { return Some(name.to_string()); } None @@ -210,6 +242,22 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // 3 | let _ = x.sum() as f64; // | ^^^ cannot infer type for `S` span + } else if let Some( + ExprKind::MethodCall(_, call_span, _), + ) = local_visitor.found_method_call.map(|e| &e.kind) { + // Point at the call instead of the whole expression: + // error[E0284]: type annotations needed + // --> file.rs:2:5 + // | + // 2 | vec![Ok(2)].into_iter().collect()?; + // | ^^^^^^^ cannot infer type + // | + // = note: cannot resolve `<_ as std::ops::Try>::Ok == _` + if span.contains(*call_span) { + *call_span + } else { + span + } } else { span }; @@ -247,12 +295,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // | consider giving `b` the explicit type `std::result::Result<i32, E>`, where // | the type parameter `E` is specified // ``` - let mut err = struct_span_err!( - self.tcx.sess, + let error_code = error_code.into(); + let mut err = self.tcx.sess.struct_span_err_with_code( err_span, - E0282, - "type annotations needed{}", - ty_msg, + &format!("type annotations needed{}", ty_msg), + error_code, ); let suffix = match local_visitor.found_ty { @@ -267,6 +314,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { &mut err, &decl.output, &body, + &descr, &name, &ret, ); @@ -334,6 +382,36 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { format!("consider giving this pattern {}", suffix) }; err.span_label(pattern.span, msg); + } else if let Some(e) = local_visitor.found_method_call { + if let ExprKind::MethodCall(segment, ..) = &e.kind { + // Suggest specifiying type params or point out the return type of the call: + // + // error[E0282]: type annotations needed + // --> $DIR/type-annotations-needed-expr.rs:2:39 + // | + // LL | let _ = x.into_iter().sum() as f64; + // | ^^^ + // | | + // | cannot infer type for `S` + // | help: consider specifying the type argument in + // | the method call: `sum::<S>` + // | + // = note: type must be known at this point + // + // or + // + // error[E0282]: type annotations needed + // --> $DIR/issue-65611.rs:59:20 + // | + // LL | let x = buffer.last().unwrap().0.clone(); + // | -------^^^^-- + // | | | + // | | cannot infer type for `T` + // | this method call resolves to `std::option::Option<&T>` + // | + // = note: type must be known at this point + self.annotate_method_call(segment, e, &mut err); + } } // Instead of the following: // error[E0282]: type annotations needed @@ -351,17 +429,66 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // | ^^^ cannot infer type for `S` // | // = note: type must be known at this point - let span = name_sp.unwrap_or(span); + let span = name_sp.unwrap_or(err_span); if !err.span.span_labels().iter().any(|span_label| { span_label.label.is_some() && span_label.span == span }) && local_visitor.found_arg_pattern.is_none() { // Avoid multiple labels pointing at `span`. - err.span_label(span, InferCtxt::missing_type_msg(&name)); + err.span_label(span, InferCtxt::missing_type_msg(&name, &descr)); } err } + /// If the `FnSig` for the method call can be found and type arguments are identified as + /// needed, suggest annotating the call, otherwise point out the resulting type of the call. + fn annotate_method_call( + &self, + segment: &hir::ptr::P<hir::PathSegment>, + e: &Expr, + err: &mut DiagnosticBuilder<'_>, + ) { + if let (Ok(snippet), Some(tables), None) = ( + self.tcx.sess.source_map().span_to_snippet(segment.ident.span), + self.in_progress_tables, + &segment.args, + ) { + let borrow = tables.borrow(); + if let Some((DefKind::Method, did)) = borrow.type_dependent_def(e.hir_id) { + let generics = self.tcx.generics_of(did); + if !generics.params.is_empty() { + err.span_suggestion( + segment.ident.span, + &format!( + "consider specifying the type argument{} in the method call", + if generics.params.len() > 1 { + "s" + } else { + "" + }, + ), + format!("{}::<{}>", snippet, generics.params.iter() + .map(|p| p.name.to_string()) + .collect::<Vec<String>>() + .join(", ")), + Applicability::HasPlaceholders, + ); + } else { + let sig = self.tcx.fn_sig(did); + let bound_output = sig.output(); + let output = bound_output.skip_binder(); + err.span_label(e.span, &format!("this method call resolves to `{:?}`", output)); + let kind = &output.kind; + if let ty::Projection(proj) | ty::UnnormalizedProjection(proj) = kind { + if let Some(span) = self.tcx.hir().span_if_local(proj.item_def_id) { + err.span_label(span, &format!("`{:?}` defined here", output)); + } + } + } + } + } + } + pub fn need_type_info_err_in_generator( &self, kind: hir::GeneratorKind, @@ -369,19 +496,19 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ty: Ty<'tcx>, ) -> DiagnosticBuilder<'tcx> { let ty = self.resolve_vars_if_possible(&ty); - let name = self.extract_type_name(&ty, None).0; + let (name, _, descr) = self.extract_type_name(&ty, None); let mut err = struct_span_err!( self.tcx.sess, span, E0698, "type inside {} must be known in this context", kind, ); - err.span_label(span, InferCtxt::missing_type_msg(&name)); + err.span_label(span, InferCtxt::missing_type_msg(&name, &descr)); err } - fn missing_type_msg(type_name: &str) -> String { + fn missing_type_msg(type_name: &str, descr: &str) -> Cow<'static, str>{ if type_name == "_" { - "cannot infer type".to_owned() + "cannot infer type".into() } else { - format!("cannot infer type for `{}`", type_name) + format!("cannot infer type for {} `{}`", descr, type_name).into() } } } diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 6a111895b56..da36b31038d 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -22,6 +22,7 @@ use crate::hir; use crate::hir::Node; use crate::hir::def_id::DefId; use crate::infer::{self, InferCtxt}; +use crate::infer::error_reporting::TypeAnnotationNeeded as ErrorCode; use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use crate::session::DiagnosticMessageId; use crate::ty::{self, AdtKind, DefIdTree, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable}; @@ -1952,7 +1953,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { return; } - match predicate { + let mut err = match predicate { ty::Predicate::Trait(ref data) => { let trait_ref = data.to_poly_trait_ref(); let self_ty = trait_ref.self_ty(); @@ -1986,59 +1987,109 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // avoid inundating the user with unnecessary errors, but we now // check upstream for type errors and dont add the obligations to // begin with in those cases. - if - self.tcx.lang_items().sized_trait() + if self.tcx.lang_items().sized_trait() .map_or(false, |sized_id| sized_id == trait_ref.def_id()) { - self.need_type_info_err(body_id, span, self_ty).emit(); - } else { - let mut err = struct_span_err!( - self.tcx.sess, - span, - E0283, - "type annotations needed: cannot resolve `{}`", - predicate, - ); - self.note_obligation_cause(&mut err, obligation); - err.emit(); + self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0282).emit(); + return; + } + let mut err = self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0283); + err.note(&format!("cannot resolve `{}`", predicate)); + if let (Ok(ref snippet), ObligationCauseCode::BindingObligation(ref def_id, _)) = ( + self.tcx.sess.source_map().span_to_snippet(span), + &obligation.cause.code, + ) { + let generics = self.tcx.generics_of(*def_id); + if !generics.params.is_empty() && !snippet.ends_with('>'){ + // FIXME: To avoid spurious suggestions in functions where type arguments + // where already supplied, we check the snippet to make sure it doesn't + // end with a turbofish. Ideally we would have access to a `PathSegment` + // instead. Otherwise we would produce the following output: + // + // error[E0283]: type annotations needed + // --> $DIR/issue-54954.rs:3:24 + // | + // LL | const ARR_LEN: usize = Tt::const_val::<[i8; 123]>(); + // | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + // | | + // | cannot infer type + // | help: consider specifying the type argument + // | in the function call: + // | `Tt::const_val::<[i8; 123]>::<T>` + // ... + // LL | const fn const_val<T: Sized>() -> usize { + // | --------- - required by this bound in `Tt::const_val` + // | + // = note: cannot resolve `_: Tt` + + err.span_suggestion( + span, + &format!( + "consider specifying the type argument{} in the function call", + if generics.params.len() > 1 { + "s" + } else { + "" + }, + ), + format!("{}::<{}>", snippet, generics.params.iter() + .map(|p| p.name.to_string()) + .collect::<Vec<String>>() + .join(", ")), + Applicability::HasPlaceholders, + ); + } } + err } ty::Predicate::WellFormed(ty) => { // Same hacky approach as above to avoid deluging user // with error messages. - if !ty.references_error() && !self.tcx.sess.has_errors() { - self.need_type_info_err(body_id, span, ty).emit(); + if ty.references_error() || self.tcx.sess.has_errors() { + return; } + self.need_type_info_err(body_id, span, ty, ErrorCode::E0282) } ty::Predicate::Subtype(ref data) => { if data.references_error() || self.tcx.sess.has_errors() { // no need to overload user in such cases - } else { - let &SubtypePredicate { a_is_expected: _, a, b } = data.skip_binder(); - // both must be type variables, or the other would've been instantiated - assert!(a.is_ty_var() && b.is_ty_var()); - self.need_type_info_err(body_id, - obligation.cause.span, - a).emit(); + return } + let &SubtypePredicate { a_is_expected: _, a, b } = data.skip_binder(); + // both must be type variables, or the other would've been instantiated + assert!(a.is_ty_var() && b.is_ty_var()); + self.need_type_info_err(body_id, span, a, ErrorCode::E0282) + } + ty::Predicate::Projection(ref data) => { + let trait_ref = data.to_poly_trait_ref(self.tcx); + let self_ty = trait_ref.self_ty(); + if predicate.references_error() { + return; + } + let mut err = self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0284); + err.note(&format!("cannot resolve `{}`", predicate)); + err } _ => { - if !self.tcx.sess.has_errors() { - let mut err = struct_span_err!( - self.tcx.sess, - obligation.cause.span, - E0284, - "type annotations needed: cannot resolve `{}`", - predicate, - ); - self.note_obligation_cause(&mut err, obligation); - err.emit(); + if self.tcx.sess.has_errors() { + return; } + let mut err = struct_span_err!( + self.tcx.sess, + span, + E0284, + "type annotations needed: cannot resolve `{}`", + predicate, + ); + err.span_label(span, &format!("cannot resolve `{}`", predicate)); + err } - } + }; + self.note_obligation_cause(&mut err, obligation); + err.emit(); } /// Returns `true` if the trait predicate may apply for *some* assignment diff --git a/src/librustc_codegen_llvm/Cargo.toml b/src/librustc_codegen_llvm/Cargo.toml index 867bbd22cfb..71cfacfa560 100644 --- a/src/librustc_codegen_llvm/Cargo.toml +++ b/src/librustc_codegen_llvm/Cargo.toml @@ -7,8 +7,28 @@ edition = "2018" [lib] name = "rustc_codegen_llvm" path = "lib.rs" -crate-type = ["dylib"] test = false +doctest = false [dependencies] +bitflags = "1.0" +flate2 = "1.0" +libc = "0.2" +log = "0.4" +rustc = { path = "../librustc" } +rustc-demangle = "0.1" +rustc_codegen_ssa = { path = "../librustc_codegen_ssa" } +rustc_codegen_utils = { path = "../librustc_codegen_utils" } +rustc_data_structures = { path = "../librustc_data_structures" } +rustc_errors = { path = "../librustc_errors" } +rustc_feature = { path = "../librustc_feature" } +rustc_fs_util = { path = "../librustc_fs_util" } +rustc_incremental = { path = "../librustc_incremental" } +rustc_index = { path = "../librustc_index" } rustc_llvm = { path = "../librustc_llvm" } +rustc_session = { path = "../librustc_session" } +rustc_target = { path = "../librustc_target" } +smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } +syntax = { path = "../libsyntax" } +syntax_expand = { path = "../libsyntax_expand" } +syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs index 1f3c8e1953e..2607a497326 100644 --- a/src/librustc_codegen_llvm/abi.rs +++ b/src/librustc_codegen_llvm/abi.rs @@ -8,6 +8,7 @@ use crate::value::Value; use rustc_codegen_ssa::MemFlags; use rustc_codegen_ssa::mir::place::PlaceRef; use rustc_codegen_ssa::mir::operand::OperandValue; +use rustc::bug; use rustc_codegen_ssa::traits::*; use rustc_target::abi::call::ArgAbi; use rustc_target::abi::{HasDataLayout, LayoutOf}; diff --git a/src/librustc_codegen_llvm/allocator.rs b/src/librustc_codegen_llvm/allocator.rs index 11b6e0befa1..e1d56b9be7a 100644 --- a/src/librustc_codegen_llvm/allocator.rs +++ b/src/librustc_codegen_llvm/allocator.rs @@ -4,6 +4,7 @@ use crate::attributes; use libc::c_uint; use rustc::ty::TyCtxt; use syntax::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS}; +use rustc::bug; use crate::ModuleLlvm; use crate::llvm::{self, False, True}; diff --git a/src/librustc_codegen_llvm/asm.rs b/src/librustc_codegen_llvm/asm.rs index abdd2e3e8db..fa43e082919 100644 --- a/src/librustc_codegen_llvm/asm.rs +++ b/src/librustc_codegen_llvm/asm.rs @@ -12,7 +12,7 @@ use syntax_pos::Span; use std::ffi::{CStr, CString}; use libc::{c_uint, c_char}; - +use log::debug; impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { fn codegen_inline_asm( diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs index 1ea9362dc42..5479a1f3144 100644 --- a/src/librustc_codegen_llvm/attributes.rs +++ b/src/librustc_codegen_llvm/attributes.rs @@ -12,6 +12,7 @@ use rustc::ty::query::Providers; use rustc_data_structures::small_c_str::SmallCStr; use rustc_data_structures::fx::FxHashMap; use rustc_target::abi::call::Conv; +use rustc_data_structures::const_cstr; use rustc_target::spec::PanicStrategy; use rustc_codegen_ssa::traits::*; diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs index 858dd59b261..0e4e4e2f983 100644 --- a/src/librustc_codegen_llvm/back/lto.rs +++ b/src/librustc_codegen_llvm/back/lto.rs @@ -4,11 +4,12 @@ use crate::back::write::{self, DiagnosticHandlers, with_llvm_pmb, save_temp_bitc use crate::llvm::archive_ro::ArchiveRO; use crate::llvm::{self, True, False}; use crate::{ModuleLlvm, LlvmCodegenBackend}; +use rustc::bug; use rustc_codegen_ssa::back::symbol_export; use rustc_codegen_ssa::back::write::{ModuleConfig, CodegenContext, FatLTOInput}; use rustc_codegen_ssa::back::lto::{SerializedModule, LtoModuleCodegen, ThinShared, ThinModule}; use rustc_codegen_ssa::traits::*; -use errors::{FatalError, Handler}; +use rustc_errors::{FatalError, Handler}; use rustc::dep_graph::WorkProduct; use rustc_session::cgu_reuse_tracker::CguReuse; use rustc::hir::def_id::LOCAL_CRATE; @@ -17,6 +18,7 @@ use rustc::session::config::{self, Lto}; use rustc::util::common::time_ext; use rustc_data_structures::fx::FxHashMap; use rustc_codegen_ssa::{RLIB_BYTECODE_EXTENSION, ModuleCodegen, ModuleKind}; +use log::{info, debug}; use std::ffi::{CStr, CString}; use std::ptr; diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index ada29c350ad..796ea7aac36 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -10,6 +10,7 @@ use crate::type_::Type; use crate::context::{is_pie_binary, get_reloc_model}; use crate::common; use crate::LlvmCodegenBackend; +use rustc::bug; use rustc::hir::def_id::LOCAL_CRATE; use rustc_codegen_ssa::back::write::{CodegenContext, ModuleConfig, run_assembler}; use rustc_codegen_ssa::traits::*; @@ -20,7 +21,8 @@ use rustc_codegen_ssa::{RLIB_BYTECODE_EXTENSION, ModuleCodegen, CompiledModule}; use rustc::util::common::time_ext; use rustc_fs_util::{path_to_c_string, link_or_copy}; use rustc_data_structures::small_c_str::SmallCStr; -use errors::{Handler, FatalError}; +use rustc_errors::{Handler, FatalError}; +use log::debug; use std::ffi::CString; use std::fs; @@ -55,7 +57,7 @@ pub const TLS_MODEL_ARGS : [(&str, llvm::ThreadLocalMode); 4] = [ ("local-exec", llvm::ThreadLocalMode::LocalExec), ]; -pub fn llvm_err(handler: &errors::Handler, msg: &str) -> FatalError { +pub fn llvm_err(handler: &rustc_errors::Handler, msg: &str) -> FatalError { match llvm::last_error() { Some(err) => handler.fatal(&format!("{}: {}", msg, err)), None => handler.fatal(&msg), @@ -63,7 +65,7 @@ pub fn llvm_err(handler: &errors::Handler, msg: &str) -> FatalError { } pub fn write_output_file( - handler: &errors::Handler, + handler: &rustc_errors::Handler, target: &'ll llvm::TargetMachine, pm: &llvm::PassManager<'ll>, m: &'ll llvm::Module, diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs index 6f72466c559..7509584df27 100644 --- a/src/librustc_codegen_llvm/builder.rs +++ b/src/librustc_codegen_llvm/builder.rs @@ -23,6 +23,8 @@ use std::ffi::CStr; use std::ops::{Deref, Range}; use std::ptr; use std::iter::TrustedLen; +use rustc_data_structures::const_cstr; +use log::debug; // All Builders must have an llfn associated with them #[must_use] diff --git a/src/librustc_codegen_llvm/callee.rs b/src/librustc_codegen_llvm/callee.rs index e0db7cae99e..c0be87b117d 100644 --- a/src/librustc_codegen_llvm/callee.rs +++ b/src/librustc_codegen_llvm/callee.rs @@ -10,6 +10,7 @@ use crate::llvm; use crate::context::CodegenCx; use crate::value::Value; use rustc_codegen_ssa::traits::*; +use log::debug; use rustc::ty::{TypeFoldable, Instance}; use rustc::ty::layout::{FnAbiExt, HasTyCtxt}; diff --git a/src/librustc_codegen_llvm/common.rs b/src/librustc_codegen_llvm/common.rs index 419e99d55d7..ff03c1f76d8 100644 --- a/src/librustc_codegen_llvm/common.rs +++ b/src/librustc_codegen_llvm/common.rs @@ -8,6 +8,8 @@ use crate::type_::Type; use crate::type_of::LayoutLlvmExt; use crate::value::Value; use rustc_codegen_ssa::traits::*; +use rustc::bug; +use log::debug; use crate::consts::const_alloc_to_llvm; use rustc::ty::layout::{HasDataLayout, LayoutOf, self, TyLayout, Size}; diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs index 297aff93a9d..11a105c1828 100644 --- a/src/librustc_codegen_llvm/consts.rs +++ b/src/librustc_codegen_llvm/consts.rs @@ -16,6 +16,8 @@ use rustc::ty::{self, Ty, Instance}; use rustc_codegen_ssa::traits::*; use syntax::symbol::{Symbol, sym}; use syntax_pos::Span; +use rustc::{bug, span_bug}; +use log::debug; use rustc::ty::layout::{self, Size, Align, LayoutOf}; diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs index 39ea1f6f5dc..2c894a5d740 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -12,6 +12,7 @@ use rustc_codegen_ssa::traits::*; use rustc_data_structures::base_n; use rustc_data_structures::small_c_str::SmallCStr; +use rustc::bug; use rustc::mir::mono::CodegenUnit; use rustc::session::config::{self, DebugInfo}; use rustc::session::Session; @@ -23,6 +24,7 @@ use rustc::util::nodemap::FxHashMap; use rustc_target::spec::{HasTargetSpec, Target}; use rustc_codegen_ssa::base::wants_msvc_seh; use crate::callee::get_fn; +use rustc_data_structures::const_cstr; use std::ffi::CStr; use std::cell::{Cell, RefCell}; diff --git a/src/librustc_codegen_llvm/debuginfo/gdb.rs b/src/librustc_codegen_llvm/debuginfo/gdb.rs index 9ed1c1730a6..739437ac27b 100644 --- a/src/librustc_codegen_llvm/debuginfo/gdb.rs +++ b/src/librustc_codegen_llvm/debuginfo/gdb.rs @@ -7,6 +7,7 @@ use crate::builder::Builder; use crate::value::Value; use rustc::session::config::DebugInfo; use rustc_codegen_ssa::traits::*; +use rustc::bug; use syntax::attr; use syntax::symbol::sym; diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 1847e4e9fa9..8327ff257c2 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -35,10 +35,13 @@ use rustc::session::config::{self, DebugInfo}; use rustc::util::nodemap::FxHashMap; use rustc_fs_util::path_to_c_string; use rustc_data_structures::small_c_str::SmallCStr; +use rustc_data_structures::const_cstr; use rustc_target::abi::HasDataLayout; use syntax::ast; use syntax::symbol::{Interner, Symbol}; use syntax_pos::{self, Span, FileName}; +use rustc::{bug, span_bug}; +use log::debug; use libc::{c_uint, c_longlong}; use std::collections::hash_map::Entry; diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs index a3782ecd92d..1de298de75f 100644 --- a/src/librustc_codegen_llvm/debuginfo/mod.rs +++ b/src/librustc_codegen_llvm/debuginfo/mod.rs @@ -33,6 +33,7 @@ use rustc_codegen_ssa::mir::debuginfo::{FunctionDebugContext, DebugScope, use libc::c_uint; use std::cell::RefCell; use std::ffi::CString; +use log::debug; use smallvec::SmallVec; use syntax_pos::{self, BytePos, Span, Pos}; diff --git a/src/librustc_codegen_llvm/debuginfo/source_loc.rs b/src/librustc_codegen_llvm/debuginfo/source_loc.rs index ccb3bde1cbe..82183fa9bd7 100644 --- a/src/librustc_codegen_llvm/debuginfo/source_loc.rs +++ b/src/librustc_codegen_llvm/debuginfo/source_loc.rs @@ -8,6 +8,7 @@ use crate::llvm; use crate::llvm::debuginfo::DIScope; use crate::builder::Builder; use rustc_codegen_ssa::traits::*; +use log::debug; use libc::c_uint; use syntax_pos::{Span, Pos}; diff --git a/src/librustc_codegen_llvm/declare.rs b/src/librustc_codegen_llvm/declare.rs index fa9fc465368..5144b92ea10 100644 --- a/src/librustc_codegen_llvm/declare.rs +++ b/src/librustc_codegen_llvm/declare.rs @@ -22,6 +22,7 @@ use rustc::ty::Ty; use rustc::session::config::Sanitizer; use rustc_data_structures::small_c_str::SmallCStr; use rustc_codegen_ssa::traits::*; +use log::debug; /// Declare a function. /// diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index 1767ad118e7..900f2d2defc 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -19,6 +19,7 @@ use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; use rustc::hir; use rustc_target::abi::HasDataLayout; use syntax::ast; +use rustc::{bug, span_bug}; use rustc_codegen_ssa::common::span_invalid_monomorphization_error; use rustc_codegen_ssa::traits::*; diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs index 00a84f8d80f..1e1d74cfa9a 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -24,33 +24,11 @@ use back::write::{create_target_machine, create_informational_target_machine}; use syntax_pos::symbol::Symbol; -extern crate rustc_demangle; -extern crate flate2; -#[macro_use] extern crate bitflags; -extern crate libc; -#[macro_use] extern crate rustc; -extern crate rustc_target; -#[macro_use] extern crate rustc_data_structures; -extern crate rustc_feature; -extern crate rustc_index; -extern crate rustc_incremental; -extern crate rustc_codegen_utils; -extern crate rustc_codegen_ssa; -extern crate rustc_fs_util; -extern crate rustc_driver as _; - -#[macro_use] extern crate log; -extern crate smallvec; -extern crate syntax; -extern crate syntax_pos; -extern crate rustc_errors as errors; -extern crate rustc_session; - use rustc_codegen_ssa::traits::*; use rustc_codegen_ssa::back::write::{CodegenContext, ModuleConfig, FatLTOInput}; use rustc_codegen_ssa::back::lto::{SerializedModule, LtoModuleCodegen, ThinModule}; use rustc_codegen_ssa::CompiledModule; -use errors::{FatalError, Handler}; +use rustc_errors::{FatalError, Handler}; use rustc::dep_graph::WorkProduct; use syntax::expand::allocator::AllocatorKind; pub use llvm_util::target_features; @@ -339,12 +317,6 @@ impl CodegenBackend for LlvmCodegenBackend { } } -/// This is the entrypoint for a hot plugged rustc_codegen_llvm -#[no_mangle] -pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> { - LlvmCodegenBackend::new() -} - pub struct ModuleLlvm { llcx: &'static mut llvm::Context, llmod_raw: *const llvm::Module, diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs index 5da3275e28e..b8a1003b118 100644 --- a/src/librustc_codegen_llvm/llvm/ffi.rs +++ b/src/librustc_codegen_llvm/llvm/ffi.rs @@ -544,6 +544,7 @@ pub type InlineAsmDiagHandler = unsafe extern "C" fn(&SMDiagnostic, *const c_voi pub mod debuginfo { use super::{InvariantOpaque, Metadata}; + use bitflags::bitflags; #[repr(C)] pub struct DIBuilder<'a>(InvariantOpaque<'a>); diff --git a/src/librustc_codegen_llvm/llvm/mod.rs b/src/librustc_codegen_llvm/llvm/mod.rs index d2d41876239..975756753d6 100644 --- a/src/librustc_codegen_llvm/llvm/mod.rs +++ b/src/librustc_codegen_llvm/llvm/mod.rs @@ -10,11 +10,11 @@ pub use self::Linkage::*; use std::str::FromStr; use std::string::FromUtf8Error; -use std::slice; use std::ffi::CStr; use std::cell::RefCell; -use libc::{c_uint, c_char, size_t}; +use libc::c_uint; use rustc_data_structures::small_c_str::SmallCStr; +use rustc_llvm::RustString; pub mod archive_ro; pub mod diagnostic; @@ -81,21 +81,6 @@ impl FromStr for ArchiveKind { } } -#[repr(C)] -pub struct RustString { - bytes: RefCell<Vec<u8>>, -} - -/// Appending to a Rust string -- used by RawRustStringOstream. -#[no_mangle] -pub unsafe extern "C" fn LLVMRustStringWriteImpl(sr: &RustString, - ptr: *const c_char, - size: size_t) { - let slice = slice::from_raw_parts(ptr as *const u8, size as usize); - - sr.bytes.borrow_mut().extend_from_slice(slice); -} - pub fn SetInstructionCallConv(instr: &'a Value, cc: CallConv) { unsafe { LLVMSetInstructionCallConv(instr, cc as c_uint); diff --git a/src/librustc_codegen_llvm/llvm_util.rs b/src/librustc_codegen_llvm/llvm_util.rs index 72612c4704e..40739387b00 100644 --- a/src/librustc_codegen_llvm/llvm_util.rs +++ b/src/librustc_codegen_llvm/llvm_util.rs @@ -8,6 +8,7 @@ use libc::c_int; use std::ffi::CString; use rustc_feature::UnstableFeatures; use syntax::symbol::sym; +use rustc::bug; use std::str; use std::slice; diff --git a/src/librustc_codegen_llvm/metadata.rs b/src/librustc_codegen_llvm/metadata.rs index cd725588811..bbe42e3b50a 100644 --- a/src/librustc_codegen_llvm/metadata.rs +++ b/src/librustc_codegen_llvm/metadata.rs @@ -6,6 +6,8 @@ use rustc_target::spec::Target; use rustc_data_structures::owning_ref::OwningRef; use rustc_codegen_ssa::METADATA_FILENAME; +use log::debug; +use rustc_data_structures::rustc_erase_owner; use std::path::Path; use std::slice; diff --git a/src/librustc_codegen_llvm/mono_item.rs b/src/librustc_codegen_llvm/mono_item.rs index cbc8af4fd27..9f6bdd23900 100644 --- a/src/librustc_codegen_llvm/mono_item.rs +++ b/src/librustc_codegen_llvm/mono_item.rs @@ -9,6 +9,7 @@ use rustc::mir::mono::{Linkage, Visibility}; use rustc::ty::{TypeFoldable, Instance}; use rustc::ty::layout::{FnAbiExt, LayoutOf}; use rustc_codegen_ssa::traits::*; +use log::debug; pub use rustc::mir::mono::MonoItem; diff --git a/src/librustc_codegen_llvm/type_.rs b/src/librustc_codegen_llvm/type_.rs index f936367572e..e6677f3d25b 100644 --- a/src/librustc_codegen_llvm/type_.rs +++ b/src/librustc_codegen_llvm/type_.rs @@ -5,6 +5,7 @@ use crate::llvm::{Bool, False, True}; use crate::context::CodegenCx; use crate::value::Value; use rustc_codegen_ssa::traits::*; +use rustc::bug; use crate::common; use crate::type_of::LayoutLlvmExt; diff --git a/src/librustc_codegen_llvm/type_of.rs b/src/librustc_codegen_llvm/type_of.rs index d77bbb27921..f9cbf4bbe45 100644 --- a/src/librustc_codegen_llvm/type_of.rs +++ b/src/librustc_codegen_llvm/type_of.rs @@ -6,6 +6,8 @@ use rustc::ty::layout::{self, Align, LayoutOf, FnAbiExt, PointeeInfo, Size, TyLa use rustc_target::abi::TyLayoutMethods; use rustc::ty::print::obsolete::DefPathBasedNames; use rustc_codegen_ssa::traits::*; +use log::debug; +use rustc::bug; use std::fmt::Write; diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml index d1cb4cbeb9b..043cfc58974 100644 --- a/src/librustc_driver/Cargo.toml +++ b/src/librustc_driver/Cargo.toml @@ -32,3 +32,6 @@ rustc_serialize = { path = "../libserialize", package = "serialize" } rustc_resolve = { path = "../librustc_resolve" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } + +[features] +llvm = ['rustc_interface/llvm'] diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 05945504db2..3230e048a3b 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -42,7 +42,7 @@ use rustc_metadata::locator; use rustc_codegen_utils::codegen_backend::CodegenBackend; use errors::{PResult, registry::Registry}; use rustc_interface::{interface, Queries}; -use rustc_interface::util::get_codegen_sysroot; +use rustc_interface::util::get_builtin_codegen_backend; use rustc_data_structures::sync::SeqCst; use rustc_feature::{find_gated_cfg, UnstableFeatures}; use rustc_serialize::json::ToJson; @@ -765,7 +765,7 @@ pub fn version(binary: &str, matches: &getopts::Matches) { println!("commit-date: {}", unw(commit_date_str())); println!("host: {}", config::host_triple()); println!("release: {}", unw(release_str())); - get_codegen_sysroot("llvm")().print_version(); + get_builtin_codegen_backend("llvm")().print_version(); } } @@ -1059,7 +1059,7 @@ pub fn handle_options(args: &[String]) -> Option<getopts::Matches> { } if cg_flags.iter().any(|x| *x == "passes=list") { - get_codegen_sysroot("llvm")().print_passes(); + get_builtin_codegen_backend("llvm")().print_passes(); return None; } diff --git a/src/librustc_interface/Cargo.toml b/src/librustc_interface/Cargo.toml index 7ab5ec2b232..58fd92822e9 100644 --- a/src/librustc_interface/Cargo.toml +++ b/src/librustc_interface/Cargo.toml @@ -25,6 +25,7 @@ rustc_traits = { path = "../librustc_traits" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_codegen_ssa = { path = "../librustc_codegen_ssa" } rustc_codegen_utils = { path = "../librustc_codegen_utils" } +rustc_codegen_llvm = { path = "../librustc_codegen_llvm", optional = true } rustc_metadata = { path = "../librustc_metadata" } rustc_mir = { path = "../librustc_mir" } rustc_passes = { path = "../librustc_passes" } @@ -39,3 +40,6 @@ once_cell = "1" [dev-dependencies] rustc_target = { path = "../librustc_target" } + +[features] +llvm = ['rustc_codegen_llvm'] diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs index 8c225b83f40..c78b3ee0767 100644 --- a/src/librustc_interface/util.rs +++ b/src/librustc_interface/util.rs @@ -16,11 +16,9 @@ use rustc_errors::registry::Registry; use rustc_metadata::dynamic_lib::DynamicLibrary; use rustc_resolve::{self, Resolver}; use std::env; -use std::env::consts::{DLL_PREFIX, DLL_SUFFIX}; use std::io::{self, Write}; use std::mem; use std::path::{Path, PathBuf}; -use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, Mutex, Once}; use std::ops::DerefMut; use smallvec::SmallVec; @@ -249,7 +247,7 @@ pub fn get_codegen_backend(sess: &Session) -> Box<dyn CodegenBackend> { filename if filename.contains(".") => { load_backend_from_dylib(filename.as_ref()) } - codegen_name => get_codegen_sysroot(codegen_name), + codegen_name => get_builtin_codegen_backend(codegen_name), }; unsafe { @@ -384,83 +382,16 @@ fn sysroot_candidates() -> Vec<PathBuf> { } } -pub fn get_codegen_sysroot(backend_name: &str) -> fn() -> Box<dyn CodegenBackend> { - // For now we only allow this function to be called once as it'll dlopen a - // few things, which seems to work best if we only do that once. In - // general this assertion never trips due to the once guard in `get_codegen_backend`, - // but there's a few manual calls to this function in this file we protect - // against. - static LOADED: AtomicBool = AtomicBool::new(false); - assert!(!LOADED.fetch_or(true, Ordering::SeqCst), - "cannot load the default codegen backend twice"); - - let target = session::config::host_triple(); - let sysroot_candidates = sysroot_candidates(); - - let sysroot = sysroot_candidates.iter() - .map(|sysroot| { - let libdir = filesearch::relative_target_lib_path(&sysroot, &target); - sysroot.join(libdir).with_file_name( - option_env!("CFG_CODEGEN_BACKENDS_DIR").unwrap_or("codegen-backends")) - }) - .filter(|f| { - info!("codegen backend candidate: {}", f.display()); - f.exists() - }) - .next(); - let sysroot = sysroot.unwrap_or_else(|| { - let candidates = sysroot_candidates.iter() - .map(|p| p.display().to_string()) - .collect::<Vec<_>>() - .join("\n* "); - let err = format!("failed to find a `codegen-backends` folder \ - in the sysroot candidates:\n* {}", candidates); - early_error(ErrorOutputType::default(), &err); - }); - info!("probing {} for a codegen backend", sysroot.display()); - - let d = sysroot.read_dir().unwrap_or_else(|e| { - let err = format!("failed to load default codegen backend, couldn't \ - read `{}`: {}", sysroot.display(), e); - early_error(ErrorOutputType::default(), &err); - }); - - let mut file: Option<PathBuf> = None; - - let expected_name = format!("rustc_codegen_llvm-{}", backend_name); - for entry in d.filter_map(|e| e.ok()) { - let path = entry.path(); - let filename = match path.file_name().and_then(|s| s.to_str()) { - Some(s) => s, - None => continue, - }; - if !(filename.starts_with(DLL_PREFIX) && filename.ends_with(DLL_SUFFIX)) { - continue - } - let name = &filename[DLL_PREFIX.len() .. filename.len() - DLL_SUFFIX.len()]; - if name != expected_name { - continue - } - if let Some(ref prev) = file { - let err = format!("duplicate codegen backends found\n\ - first: {}\n\ - second: {}\n\ - ", prev.display(), path.display()); - early_error(ErrorOutputType::default(), &err); - } - file = Some(path.clone()); - } - - match file { - Some(ref s) => return load_backend_from_dylib(s), - None => { - let err = format!("failed to load default codegen backend for `{}`, \ - no appropriate codegen dylib found in `{}`", - backend_name, sysroot.display()); - early_error(ErrorOutputType::default(), &err); +pub fn get_builtin_codegen_backend(backend_name: &str) -> fn() -> Box<dyn CodegenBackend> { + #[cfg(feature = "llvm")] + { + if backend_name == "llvm" { + return rustc_codegen_llvm::LlvmCodegenBackend::new; } } + let err = format!("unsupported builtin codegen backend `{}`", backend_name); + early_error(ErrorOutputType::default(), &err); } pub(crate) fn compute_crate_disambiguator(session: &Session) -> CrateDisambiguator { diff --git a/src/librustc_llvm/Cargo.toml b/src/librustc_llvm/Cargo.toml index 0fe327d5dee..4fc02e348f6 100644 --- a/src/librustc_llvm/Cargo.toml +++ b/src/librustc_llvm/Cargo.toml @@ -13,6 +13,9 @@ path = "lib.rs" static-libstdcpp = [] emscripten = [] +[dependencies] +libc = "0.2" + [build-dependencies] build_helper = { path = "../build_helper" } cc = "1.0.1" diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index 647d473f015..9c8943a9559 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -5,6 +5,26 @@ // NOTE: This crate only exists to allow linking on mingw targets. +use std::cell::RefCell; +use std::slice; +use libc::{c_char, size_t}; + + +#[repr(C)] +pub struct RustString { + pub bytes: RefCell<Vec<u8>>, +} + +/// Appending to a Rust string -- used by RawRustStringOstream. +#[no_mangle] +pub unsafe extern "C" fn LLVMRustStringWriteImpl(sr: &RustString, + ptr: *const c_char, + size: size_t) { + let slice = slice::from_raw_parts(ptr as *const u8, size as usize); + + sr.bytes.borrow_mut().extend_from_slice(slice); +} + /// Initialize targets enabled by the build script via `cfg(llvm_component = "...")`. /// N.B., this function can't be moved to `rustc_codegen_llvm` because of the `cfg`s. pub fn initialize_available_targets() { diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 37a9381271a..c3720328506 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -238,7 +238,7 @@ use super::{FieldPat, Pat, PatKind, PatRange}; use rustc::hir::def_id::DefId; use rustc::hir::{HirId, RangeEnd}; use rustc::ty::layout::{Integer, IntegerExt, Size, VariantIdx}; -use rustc::ty::{self, Const, Ty, TyCtxt, TypeFoldable}; +use rustc::ty::{self, Const, Ty, TyCtxt, TypeFoldable, VariantDef}; use rustc::lint; use rustc::mir::interpret::{truncate, AllocId, ConstValue, Pointer, Scalar}; @@ -354,7 +354,7 @@ impl PatternFolder<'tcx> for LiteralExpander<'tcx> { } impl<'tcx> Pat<'tcx> { - fn is_wildcard(&self) -> bool { + pub(super) fn is_wildcard(&self) -> bool { match *self.kind { PatKind::Binding { subpattern: None, .. } | PatKind::Wild => true, _ => false, @@ -596,9 +596,21 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> { } } - fn is_local(&self, ty: Ty<'tcx>) -> bool { + // Returns whether the given type is an enum from another crate declared `#[non_exhaustive]`. + pub fn is_foreign_non_exhaustive_enum(&self, ty: Ty<'tcx>) -> bool { match ty.kind { - ty::Adt(adt_def, ..) => adt_def.did.is_local(), + ty::Adt(def, ..) => { + def.is_enum() && def.is_variant_list_non_exhaustive() && !def.did.is_local() + } + _ => false, + } + } + + // Returns whether the given variant is from another crate and has its fields declared + // `#[non_exhaustive]`. + fn is_foreign_non_exhaustive_variant(&self, ty: Ty<'tcx>, variant: &VariantDef) -> bool { + match ty.kind { + ty::Adt(def, ..) => variant.is_field_list_non_exhaustive() && !def.did.is_local(), _ => false, } } @@ -758,6 +770,10 @@ impl<'tcx> Constructor<'tcx> { // Returns the set of constructors covered by `self` but not by // anything in `other_ctors`. fn subtract_ctors(&self, other_ctors: &Vec<Constructor<'tcx>>) -> Vec<Constructor<'tcx>> { + if other_ctors.is_empty() { + return vec![self.clone()]; + } + match self { // Those constructors can only match themselves. Single | Variant(_) | ConstantValue(..) | FloatRange(..) => { @@ -858,8 +874,7 @@ impl<'tcx> Constructor<'tcx> { vec![Pat::wildcard_from_ty(substs.type_at(0))] } else { let variant = &adt.variants[self.variant_index_for_adt(cx, adt)]; - let is_non_exhaustive = - variant.is_field_list_non_exhaustive() && !cx.is_local(ty); + let is_non_exhaustive = cx.is_foreign_non_exhaustive_variant(ty, variant); variant .fields .iter() @@ -1205,6 +1220,8 @@ impl<'tcx> Witness<'tcx> { /// /// We make sure to omit constructors that are statically impossible. E.g., for /// `Option<!>`, we do not include `Some(_)` in the returned list of constructors. +/// Invariant: this returns an empty `Vec` if and only if the type is uninhabited (as determined by +/// `cx.is_uninhabited()`). fn all_constructors<'a, 'tcx>( cx: &mut MatchCheckCtxt<'a, 'tcx>, pcx: PatCtxt<'tcx>, @@ -1235,47 +1252,45 @@ fn all_constructors<'a, 'tcx>( vec![Slice(Slice { array_len: None, kind })] } ty::Adt(def, substs) if def.is_enum() => { - let ctors: Vec<_> = def - .variants - .iter() - .filter(|v| { - !cx.tcx.features().exhaustive_patterns - || !v - .uninhabited_from(cx.tcx, substs, def.adt_kind()) + let ctors: Vec<_> = if cx.tcx.features().exhaustive_patterns { + // If `exhaustive_patterns` is enabled, we exclude variants known to be + // uninhabited. + def.variants + .iter() + .filter(|v| { + !v.uninhabited_from(cx.tcx, substs, def.adt_kind()) .contains(cx.tcx, cx.module) - }) - .map(|v| Variant(v.def_id)) - .collect(); - - // If our scrutinee is *privately* an empty enum, we must treat it as though it had an - // "unknown" constructor (in that case, all other patterns obviously can't be variants) - // to avoid exposing its emptyness. See the `match_privately_empty` test for details. - // FIXME: currently the only way I know of something can be a privately-empty enum is - // when the exhaustive_patterns feature flag is not present, so this is only needed for - // that case. - let is_privately_empty = ctors.is_empty() && !cx.is_uninhabited(pcx.ty); - // If the enum is declared as `#[non_exhaustive]`, we treat it as if it had an - // additionnal "unknown" constructor. - let is_declared_nonexhaustive = - def.is_variant_list_non_exhaustive() && !cx.is_local(pcx.ty); - - if is_privately_empty || is_declared_nonexhaustive { - // There is no point in enumerating all possible variants, because the user can't - // actually match against them themselves. So we return only the fictitious - // constructor. - // E.g., in an example like: - // ``` - // let err: io::ErrorKind = ...; - // match err { - // io::ErrorKind::NotFound => {}, - // } - // ``` - // we don't want to show every possible IO error, but instead have only `_` as the - // witness. - vec![NonExhaustive] + }) + .map(|v| Variant(v.def_id)) + .collect() } else { - ctors - } + def.variants.iter().map(|v| Variant(v.def_id)).collect() + }; + + // If the enum is declared as `#[non_exhaustive]`, we treat it as if it had an + // additional "unknown" constructor. + // There is no point in enumerating all possible variants, because the user can't + // actually match against them all themselves. So we always return only the fictitious + // constructor. + // E.g., in an example like: + // ``` + // let err: io::ErrorKind = ...; + // match err { + // io::ErrorKind::NotFound => {}, + // } + // ``` + // we don't want to show every possible IO error, but instead have only `_` as the + // witness. + let is_declared_nonexhaustive = cx.is_foreign_non_exhaustive_enum(pcx.ty); + + // If `exhaustive_patterns` is disabled and our scrutinee is an empty enum, we treat it + // as though it had an "unknown" constructor to avoid exposing its emptyness. Note that + // an empty match will still be considered exhaustive because that case is handled + // separately in `check_match`. + let is_secretly_empty = + def.variants.is_empty() && !cx.tcx.features().exhaustive_patterns; + + if is_secretly_empty || is_declared_nonexhaustive { vec![NonExhaustive] } else { ctors } } ty::Char => { vec![ @@ -1605,6 +1620,7 @@ pub fn is_useful<'p, 'tcx>( v: &PatStack<'p, 'tcx>, witness_preference: WitnessPreference, hir_id: HirId, + is_top_level: bool, ) -> Usefulness<'tcx, 'p> { let &Matrix(ref rows) = matrix; debug!("is_useful({:#?}, {:#?})", matrix, v); @@ -1632,7 +1648,7 @@ pub fn is_useful<'p, 'tcx>( let mut unreachable_pats = Vec::new(); let mut any_is_useful = false; for v in vs { - let res = is_useful(cx, &matrix, &v, witness_preference, hir_id); + let res = is_useful(cx, &matrix, &v, witness_preference, hir_id, false); match res { Useful(pats) => { any_is_useful = true; @@ -1732,7 +1748,7 @@ pub fn is_useful<'p, 'tcx>( } else { let matrix = matrix.specialize_wildcard(); let v = v.to_tail(); - let usefulness = is_useful(cx, &matrix, &v, witness_preference, hir_id); + let usefulness = is_useful(cx, &matrix, &v, witness_preference, hir_id, false); // In this case, there's at least one "free" // constructor that is only matched against by @@ -1761,7 +1777,10 @@ pub fn is_useful<'p, 'tcx>( // `(<direction-1>, <direction-2>, true)` - we are // satisfied with `(_, _, true)`. In this case, // `used_ctors` is empty. - if missing_ctors.all_ctors_are_missing() { + // The exception is: if we are at the top-level, for example in an empty match, we + // sometimes prefer reporting the list of constructors instead of just `_`. + let report_ctors_rather_than_wildcard = is_top_level && !IntRange::is_integral(pcx.ty); + if missing_ctors.all_ctors_are_missing() && !report_ctors_rather_than_wildcard { // All constructors are unused. Add a wild pattern // rather than each individual constructor. usefulness.apply_wildcard(pcx.ty) @@ -1793,7 +1812,7 @@ fn is_useful_specialized<'p, 'tcx>( cx.pattern_arena.alloc_from_iter(ctor.wildcard_subpatterns(cx, lty)); let matrix = matrix.specialize_constructor(cx, &ctor, ctor_wild_subpatterns); v.specialize_constructor(cx, &ctor, ctor_wild_subpatterns) - .map(|v| is_useful(cx, &matrix, &v, witness_preference, hir_id)) + .map(|v| is_useful(cx, &matrix, &v, witness_preference, hir_id, false)) .map(|u| u.apply_constructor(cx, &ctor, lty)) .unwrap_or(NotUseful) } @@ -2308,7 +2327,7 @@ fn specialize_one_pattern<'p, 'tcx>( PatKind::Variant { adt_def, variant_index, ref subpatterns, .. } => { let ref variant = adt_def.variants[variant_index]; - let is_non_exhaustive = variant.is_field_list_non_exhaustive() && !cx.is_local(pat.ty); + let is_non_exhaustive = cx.is_foreign_non_exhaustive_variant(pat.ty, variant); Some(Variant(variant.def_id)) .filter(|variant_constructor| variant_constructor == constructor) .map(|_| { diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index 737af3e1358..8156cfe7ab5 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -148,8 +148,8 @@ impl<'tcx> MatchVisitor<'_, 'tcx> { self.tables, ); patcx.include_lint_checks(); - let pattern: &_ = - cx.pattern_arena.alloc(expand_pattern(cx, patcx.lower_pattern(&arm.pat))); + let pattern = patcx.lower_pattern(&arm.pat); + let pattern: &_ = cx.pattern_arena.alloc(expand_pattern(cx, pattern)); if !patcx.errors.is_empty() { patcx.report_inlining_errors(arm.pat.span); have_errors = true; @@ -166,73 +166,12 @@ impl<'tcx> MatchVisitor<'_, 'tcx> { // Fourth, check for unreachable arms. let matrix = check_arms(cx, &inlined_arms, source); - // Then, if the match has no arms, check whether the scrutinee - // is uninhabited. - let pat_ty = self.tables.node_type(scrut.hir_id); - let module = self.tcx.hir().get_module_parent(scrut.hir_id); - let mut def_span = None; - let mut missing_variants = vec![]; - if inlined_arms.is_empty() { - let scrutinee_is_uninhabited = if self.tcx.features().exhaustive_patterns { - self.tcx.is_ty_uninhabited_from(module, pat_ty) - } else { - match pat_ty.kind { - ty::Never => true, - ty::Adt(def, _) => { - def_span = self.tcx.hir().span_if_local(def.did); - if def.variants.len() < 4 && !def.variants.is_empty() { - // keep around to point at the definition of non-covered variants - missing_variants = - def.variants.iter().map(|variant| variant.ident).collect(); - } - - let is_non_exhaustive_and_non_local = - def.is_variant_list_non_exhaustive() && !def.did.is_local(); - - !(is_non_exhaustive_and_non_local) && def.variants.is_empty() - } - _ => false, - } - }; - if !scrutinee_is_uninhabited { - // We know the type is inhabited, so this must be wrong - let mut err = create_e0004( - self.tcx.sess, - scrut.span, - format!( - "non-exhaustive patterns: {}", - match missing_variants.len() { - 0 => format!("type `{}` is non-empty", pat_ty), - 1 => format!( - "pattern `{}` of type `{}` is not handled", - missing_variants[0].name, pat_ty, - ), - _ => format!( - "multiple patterns of type `{}` are not handled", - pat_ty - ), - } - ), - ); - err.help( - "ensure that all possible cases are being handled, \ - possibly by adding wildcards or more match arms", - ); - if let Some(sp) = def_span { - err.span_label(sp, format!("`{}` defined here", pat_ty)); - } - // point at the definition of non-covered enum variants - for variant in &missing_variants { - err.span_label(variant.span, "variant not covered"); - } - err.emit(); - } - // If the type *is* uninhabited, it's vacuously exhaustive - return; - } - + // Fifth, check if the match is exhaustive. let scrut_ty = self.tables.node_type(scrut.hir_id); - check_exhaustive(cx, scrut_ty, scrut.span, &matrix, scrut.hir_id); + // Note: An empty match isn't the same as an empty matrix for diagnostics purposes, + // since an empty matrix can occur when there are arms, if those arms all have guards. + let is_empty_match = inlined_arms.is_empty(); + check_exhaustive(cx, scrut_ty, scrut.span, &matrix, scrut.hir_id, is_empty_match); }) } @@ -390,7 +329,7 @@ fn check_arms<'p, 'tcx>( for (arm_index, (pat, hir_pat, has_guard)) in arms.iter().enumerate() { let v = PatStack::from_pattern(pat); - match is_useful(cx, &seen, &v, LeaveOutWitness, hir_pat.hir_id) { + match is_useful(cx, &seen, &v, LeaveOutWitness, hir_pat.hir_id, true) { NotUseful => { match source { hir::MatchSource::IfDesugar { .. } | hir::MatchSource::WhileDesugar => bug!(), @@ -478,7 +417,8 @@ fn check_not_useful<'p, 'tcx>( hir_id: HirId, ) -> Result<(), Vec<super::Pat<'tcx>>> { let wild_pattern = cx.pattern_arena.alloc(super::Pat::wildcard_from_ty(ty)); - match is_useful(cx, matrix, &PatStack::from_pattern(wild_pattern), ConstructWitness, hir_id) { + let v = PatStack::from_pattern(wild_pattern); + match is_useful(cx, matrix, &v, ConstructWitness, hir_id, true) { NotUseful => Ok(()), // This is good, wildcard pattern isn't reachable. UsefulWithWitness(pats) => Err(if pats.is_empty() { bug!("Exhaustiveness check returned no witnesses") @@ -495,25 +435,60 @@ fn check_exhaustive<'p, 'tcx>( sp: Span, matrix: &Matrix<'p, 'tcx>, hir_id: HirId, + is_empty_match: bool, ) { + // In the absence of the `exhaustive_patterns` feature, empty matches are not detected by + // `is_useful` to exhaustively match uninhabited types, so we manually check here. + if is_empty_match && !cx.tcx.features().exhaustive_patterns { + let scrutinee_is_visibly_uninhabited = match scrut_ty.kind { + ty::Never => true, + ty::Adt(def, _) => { + def.is_enum() + && def.variants.is_empty() + && !cx.is_foreign_non_exhaustive_enum(scrut_ty) + } + _ => false, + }; + if scrutinee_is_visibly_uninhabited { + // If the type *is* uninhabited, an empty match is vacuously exhaustive. + return; + } + } + let witnesses = match check_not_useful(cx, scrut_ty, matrix, hir_id) { Ok(_) => return, Err(err) => err, }; - let joined_patterns = joined_uncovered_patterns(&witnesses); - let mut err = create_e0004( - cx.tcx.sess, - sp, - format!("non-exhaustive patterns: {} not covered", joined_patterns), - ); - err.span_label(sp, pattern_not_covered_label(&witnesses, &joined_patterns)); + let non_empty_enum = match scrut_ty.kind { + ty::Adt(def, _) => def.is_enum() && !def.variants.is_empty(), + _ => false, + }; + // In the case of an empty match, replace the '`_` not covered' diagnostic with something more + // informative. + let mut err; + if is_empty_match && !non_empty_enum { + err = create_e0004( + cx.tcx.sess, + sp, + format!("non-exhaustive patterns: type `{}` is non-empty", scrut_ty), + ); + } else { + let joined_patterns = joined_uncovered_patterns(&witnesses); + err = create_e0004( + cx.tcx.sess, + sp, + format!("non-exhaustive patterns: {} not covered", joined_patterns), + ); + err.span_label(sp, pattern_not_covered_label(&witnesses, &joined_patterns)); + }; + adt_defined_here(cx, &mut err, scrut_ty, &witnesses); err.help( "ensure that all possible cases are being handled, \ possibly by adding wildcards or more match arms", - ) - .emit(); + ); + err.emit(); } fn joined_uncovered_patterns(witnesses: &[super::Pat<'_>]) -> String { diff --git a/src/librustc_mir/interpret/traits.rs b/src/librustc_mir/interpret/traits.rs index efa0d266cbc..916ea3dc393 100644 --- a/src/librustc_mir/interpret/traits.rs +++ b/src/librustc_mir/interpret/traits.rs @@ -140,7 +140,18 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let fn_sig = drop_instance.ty(*self.tcx).fn_sig(*self.tcx); let fn_sig = self.tcx.normalize_erasing_late_bound_regions(self.param_env, &fn_sig); // The drop function takes `*mut T` where `T` is the type being dropped, so get that. - let ty = fn_sig.inputs()[0].builtin_deref(true).unwrap().ty; + let args = fn_sig.inputs(); + if args.len() != 1 { + throw_ub_format!( + "drop fn should have 1 argument, but signature is {:?}", fn_sig + ); + } + let ty = args[0].builtin_deref(true) + .ok_or_else(|| err_ub_format!( + "drop fn argument type {} is not a pointer type", + args[0] + ))? + .ty; Ok((drop_instance, ty)) } diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index e358df2f213..1dbcfe5588e 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -22,28 +22,23 @@ use super::{ macro_rules! throw_validation_failure { ($what:expr, $where:expr, $details:expr) => {{ - let where_ = path_format(&$where); - let where_ = if where_.is_empty() { - String::new() - } else { - format!(" at {}", where_) - }; - throw_unsup!(ValidationFailure(format!( - "encountered {}{}, but expected {}", - $what, where_, $details, - ))) + let mut msg = format!("encountered {}", $what); + let where_ = &$where; + if !where_.is_empty() { + msg.push_str(" at "); + write_path(&mut msg, where_); + } + write!(&mut msg, ", but expected {}", $details).unwrap(); + throw_unsup!(ValidationFailure(msg)) }}; ($what:expr, $where:expr) => {{ - let where_ = path_format(&$where); - let where_ = if where_.is_empty() { - String::new() - } else { - format!(" at {}", where_) - }; - throw_unsup!(ValidationFailure(format!( - "encountered {}{}", - $what, where_, - ))) + let mut msg = format!("encountered {}", $what); + let where_ = &$where; + if !where_.is_empty() { + msg.push_str(" at "); + write_path(&mut msg, where_); + } + throw_unsup!(ValidationFailure(msg)) }}; } @@ -60,7 +55,7 @@ macro_rules! try_validation { Ok(x) => x, Err(_) => throw_validation_failure!($what, $where), } - }} + }}; } /// We want to show a nice path to the invalid field for diagnostics, @@ -113,10 +108,9 @@ impl<T: Copy + Eq + Hash + std::fmt::Debug, PATH: Default> RefTracking<T, PATH> } /// Format a path -fn path_format(path: &Vec<PathElem>) -> String { +fn write_path(out: &mut String, path: &Vec<PathElem>) { use self::PathElem::*; - let mut out = String::new(); for elem in path.iter() { match elem { Field(name) => write!(out, ".{}", name), @@ -135,7 +129,6 @@ fn path_format(path: &Vec<PathElem>) -> String { DynDowncast => write!(out, ".<dyn-downcast>"), }.unwrap() } - out } // Test if a range that wraps at overflow contains `test` @@ -428,7 +421,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> err_unsup!(InvalidNullPointerUsage) => throw_validation_failure!("NULL reference", self.path), err_unsup!(AlignmentCheckFailed { required, has }) => - throw_validation_failure!(format!("unaligned reference \ + throw_validation_failure!(format_args!("unaligned reference \ (required {} byte alignment but found {})", required.bytes(), has.bytes()), self.path), err_unsup!(ReadBytesAsPointer) => @@ -519,7 +512,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> let value = try_validation!(value.not_undef(), value, self.path, - format!( + format_args!( "something {}", wrapping_range_format(&layout.valid_range, max_hi), ) @@ -532,7 +525,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> throw_validation_failure!( "a potentially NULL pointer", self.path, - format!( + format_args!( "something that cannot possibly fail to be {}", wrapping_range_format(&layout.valid_range, max_hi) ) @@ -545,7 +538,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> throw_validation_failure!( "a pointer", self.path, - format!( + format_args!( "something that cannot possibly fail to be {}", wrapping_range_format(&layout.valid_range, max_hi) ) @@ -562,7 +555,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> throw_validation_failure!( bits, self.path, - format!("something {}", wrapping_range_format(&layout.valid_range, max_hi)) + format_args!("something {}", wrapping_range_format(&layout.valid_range, max_hi)) ) } } diff --git a/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs b/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs index dbcd77bc753..2c9ba9f2ca9 100644 --- a/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs +++ b/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs @@ -7,7 +7,7 @@ pub fn target() -> Result<Target, String> { "--as-needed", "--eh-frame-hdr", "-z" , "noexecstack", - "-e","sgx_entry", + "-e","elf_entry", "-Bstatic", "--gc-sections", "-z","text", diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index 253fc5575c5..726b3ba9857 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -1289,8 +1289,20 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { } // Error possibly reported in `check_assign` so avoid emitting error again. - err.emit_unless(expression.filter(|e| fcx.is_assign_to_bool(e, expected)) - .is_some()); + let assign_to_bool = expression + // #67273: Use initial expected type as opposed to `expected`. + // Otherwise we end up using prior coercions in e.g. a `match` expression: + // ``` + // match i { + // 0 => true, // Because of this... + // 1 => i = 1, // ...`expected == bool` now, but not when checking `i = 1`. + // _ => (), + // }; + // ``` + .filter(|e| fcx.is_assign_to_bool(e, self.expected_ty())) + .is_some(); + + err.emit_unless(assign_to_bool); self.final_ty = Some(fcx.tcx.types.err); } diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index 5bfc60c7540..fc7d1976637 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -871,6 +871,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let method = match self.lookup_method(rcvr_t, segment, span, expr, rcvr) { Ok(method) => { + // We could add a "consider `foo::<params>`" suggestion here, but I wasn't able to + // trigger this codepath causing `structuraly_resolved_type` to emit an error. + self.write_method_call(expr.hir_id, method); Ok(method) } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index a956aba4f62..43e7bbcf0c0 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -103,6 +103,7 @@ use rustc_index::vec::Idx; use rustc_target::spec::abi::Abi; use rustc::infer::opaque_types::OpaqueTypeDecl; use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use rustc::infer::error_reporting::TypeAnnotationNeeded::E0282; use rustc::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; use rustc::middle::region; use rustc::mir::interpret::{ConstValue, GlobalId}; @@ -5359,7 +5360,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty } else { if !self.is_tainted_by_errors() { - self.need_type_info_err((**self).body_id, sp, ty) + self.need_type_info_err((**self).body_id, sp, ty, E0282) .note("type must be known at this point") .emit(); } diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 3113e9b241d..35f25b322e0 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -8,6 +8,7 @@ use rustc::hir; use rustc::hir::def_id::{DefId, DefIndex}; use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc::infer::InferCtxt; +use rustc::infer::error_reporting::TypeAnnotationNeeded::E0282; use rustc::ty::adjustment::{Adjust, Adjustment, PointerCast}; use rustc::ty::fold::{TypeFoldable, TypeFolder}; use rustc::ty::{self, Ty, TyCtxt}; @@ -717,7 +718,7 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> { fn report_error(&self, t: Ty<'tcx>) { if !self.tcx.sess.has_errors() { self.infcx - .need_type_info_err(Some(self.body.id()), self.span.to_span(self.tcx), t) + .need_type_info_err(Some(self.body.id()), self.span.to_span(self.tcx), t, E0282) .emit(); } } diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index e3de7fe2049..f2822916d3c 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -12,4 +12,6 @@ path = "lib.rs" pulldown-cmark = { version = "0.5.3", default-features = false } minifier = "0.0.33" rayon = { version = "0.3.0", package = "rustc-rayon" } +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" tempfile = "3" diff --git a/src/librustdoc/html/item_type.rs b/src/librustdoc/html/item_type.rs index f5e45924893..85f132378b1 100644 --- a/src/librustdoc/html/item_type.rs +++ b/src/librustdoc/html/item_type.rs @@ -1,7 +1,11 @@ //! Item types. use std::fmt; + +use serde::{Serialize, Serializer}; + use syntax_pos::hygiene::MacroKind; + use crate::clean; /// Item type. Corresponds to `clean::ItemEnum` variants. @@ -45,6 +49,14 @@ pub enum ItemType { TraitAlias = 25, } +impl Serialize for ItemType { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + (*self as u8).serialize(serializer) + } +} impl<'a> From<&'a clean::Item> for ItemType { fn from(item: &'a clean::Item) -> ItemType { diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 86e5efbd7b3..e764b7ee527 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -31,7 +31,8 @@ use std::cmp::Ordering; use std::collections::{BTreeMap, VecDeque}; use std::default::Default; use std::error; -use std::fmt::{self, Formatter, Write as FmtWrite}; + +use std::fmt::{self, Formatter, Write}; use std::ffi::OsStr; use std::fs::{self, File}; use std::io::prelude::*; @@ -42,7 +43,8 @@ use std::sync::Arc; use std::rc::Rc; use errors; -use serialize::json::{ToJson, Json, as_json}; +use serde::{Serialize, Serializer}; +use serde::ser::SerializeSeq; use syntax::ast; use syntax::edition::Edition; use syntax::print::pprust; @@ -303,19 +305,22 @@ struct IndexItem { search_type: Option<IndexItemFunctionType>, } -impl ToJson for IndexItem { - fn to_json(&self) -> Json { +impl Serialize for IndexItem { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { assert_eq!(self.parent.is_some(), self.parent_idx.is_some()); - let mut data = Vec::with_capacity(6); - data.push((self.ty as usize).to_json()); - data.push(self.name.to_json()); - data.push(self.path.to_json()); - data.push(self.desc.to_json()); - data.push(self.parent_idx.to_json()); - data.push(self.search_type.to_json()); - - Json::Array(data) + ( + self.ty, + &self.name, + &self.path, + &self.desc, + self.parent_idx, + &self.search_type, + ) + .serialize(serializer) } } @@ -326,18 +331,20 @@ struct Type { generics: Option<Vec<String>>, } -impl ToJson for Type { - fn to_json(&self) -> Json { - match self.name { - Some(ref name) => { - let mut data = Vec::with_capacity(2); - data.push(name.to_json()); - if let Some(ref generics) = self.generics { - data.push(generics.to_json()); - } - Json::Array(data) +impl Serialize for Type { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + if let Some(name) = &self.name { + let mut seq = serializer.serialize_seq(None)?; + seq.serialize_element(&name)?; + if let Some(generics) = &self.generics { + seq.serialize_element(&generics)?; } - None => Json::Null, + seq.end() + } else { + serializer.serialize_none() } } } @@ -349,26 +356,29 @@ struct IndexItemFunctionType { output: Option<Vec<Type>>, } -impl ToJson for IndexItemFunctionType { - fn to_json(&self) -> Json { +impl Serialize for IndexItemFunctionType { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { // If we couldn't figure out a type, just write `null`. let mut iter = self.inputs.iter(); if match self.output { Some(ref output) => iter.chain(output.iter()).any(|ref i| i.name.is_none()), None => iter.any(|ref i| i.name.is_none()), } { - Json::Null + serializer.serialize_none() } else { - let mut data = Vec::with_capacity(2); - data.push(self.inputs.to_json()); - if let Some(ref output) = self.output { + let mut seq = serializer.serialize_seq(None)?; + seq.serialize_element(&self.inputs)?; + if let Some(output) = &self.output { if output.len() > 1 { - data.push(output.to_json()); + seq.serialize_element(&output)?; } else { - data.push(output[0].to_json()); + seq.serialize_element(&output[0])?; } } - Json::Array(data) + seq.end() } } } @@ -596,7 +606,7 @@ fn write_shared( // To avoid theme switch latencies as much as possible, we put everything theme related // at the beginning of the html files into another js file. let theme_js = format!( -r#"var themes = document.getElementById("theme-choices"); + r#"var themes = document.getElementById("theme-choices"); var themePicker = document.getElementById("theme-picker"); function showThemeButtonState() {{ @@ -642,8 +652,8 @@ themePicker.onblur = handleThemeButtonsBlur; }}; but.onblur = handleThemeButtonsBlur; themes.appendChild(but); -}});"#, - as_json(&themes)); +}});"#, serde_json::to_string(&themes).unwrap()); + write_minify(&cx.shared.fs, cx.path("theme.js"), &theme_js, options.enable_minification)?; @@ -932,32 +942,48 @@ themePicker.onblur = handleThemeButtonsBlur; } }; - let mut have_impls = false; - let mut implementors = format!(r#"implementors["{}"] = ["#, krate.name); - for imp in imps { - // If the trait and implementation are in the same crate, then - // there's no need to emit information about it (there's inlining - // going on). If they're in different crates then the crate defining - // the trait will be interested in our implementation. - if imp.impl_item.def_id.krate == did.krate { continue } - // If the implementation is from another crate then that crate - // should add it. - if !imp.impl_item.def_id.is_local() { continue } - have_impls = true; - write!(implementors, "{{text:{},synthetic:{},types:{}}},", - as_json(&imp.inner_impl().print().to_string()), - imp.inner_impl().synthetic, - as_json(&collect_paths_for_type(imp.inner_impl().for_.clone()))).unwrap(); + #[derive(Serialize)] + struct Implementor { + text: String, + synthetic: bool, + types: Vec<String>, } - implementors.push_str("];"); + + let implementors = imps + .iter() + .filter_map(|imp| { + // If the trait and implementation are in the same crate, then + // there's no need to emit information about it (there's inlining + // going on). If they're in different crates then the crate defining + // the trait will be interested in our implementation. + // + // If the implementation is from another crate then that crate + // should add it. + if imp.impl_item.def_id.krate == did.krate || !imp.impl_item.def_id.is_local() { + None + } else { + Some(Implementor { + text: imp.inner_impl().print().to_string(), + synthetic: imp.inner_impl().synthetic, + types: collect_paths_for_type(imp.inner_impl().for_.clone()), + }) + } + }) + .collect::<Vec<_>>(); // Only create a js file if we have impls to add to it. If the trait is // documented locally though we always create the file to avoid dead // links. - if !have_impls && !cx.cache.paths.contains_key(&did) { + if implementors.is_empty() && !cx.cache.paths.contains_key(&did) { continue; } + let implementors = format!( + r#"implementors["{}"] = {};"#, + krate.name, + serde_json::to_string(&implementors).unwrap() + ); + let mut mydst = dst.clone(); for part in &remote_path[..remote_path.len() - 1] { mydst.push(part); @@ -1456,7 +1482,7 @@ impl Context { if !self.render_redirect_pages { let items = self.build_sidebar_items(&m); let js_dst = self.dst.join("sidebar-items.js"); - let v = format!("initSidebarItems({});", as_json(&items)); + let v = format!("initSidebarItems({});", serde_json::to_string(&items).unwrap()); scx.fs.write(&js_dst, &v)?; } @@ -2558,8 +2584,11 @@ fn item_trait( write_loading_content(w, "</div>"); } } - write!(w, r#"<script type="text/javascript">window.inlined_types=new Set({});</script>"#, - as_json(&synthetic_types)); + write!( + w, + r#"<script type="text/javascript">window.inlined_types=new Set({});</script>"#, + serde_json::to_string(&synthetic_types).unwrap(), + ); write!(w, r#"<script type="text/javascript" async src="{root_path}/implementors/{path}/{ty}.{name}.js"> diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs index 65dd119c27c..d80facf4704 100644 --- a/src/librustdoc/html/render/cache.rs +++ b/src/librustdoc/html/render/cache.rs @@ -8,7 +8,8 @@ use std::path::{Path, PathBuf}; use std::collections::BTreeMap; use syntax::source_map::FileName; use syntax::symbol::sym; -use serialize::json::{ToJson, Json, as_json}; + +use serde::Serialize; use super::{ItemType, IndexItem, IndexItemFunctionType, Impl, shorten, plain_summary_line}; use super::{Type, RenderInfo}; @@ -544,7 +545,7 @@ fn extern_location(e: &clean::ExternalCrate, extern_url: Option<&str>, dst: &Pat fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { let mut nodeid_to_pathid = FxHashMap::default(); let mut crate_items = Vec::with_capacity(cache.search_index.len()); - let mut crate_paths = Vec::<Json>::new(); + let mut crate_paths = vec![]; let Cache { ref mut search_index, ref orphan_impl_items, @@ -581,7 +582,7 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { lastpathid += 1; let &(ref fqp, short) = paths.get(&nodeid).unwrap(); - crate_paths.push(((short as usize), fqp.last().unwrap().clone()).to_json()); + crate_paths.push((short, fqp.last().unwrap().clone())); pathid } }); @@ -592,22 +593,33 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { } else { lastpath = item.path.clone(); } - crate_items.push(item.to_json()); + crate_items.push(&*item); } let crate_doc = krate.module.as_ref().map(|module| { shorten(plain_summary_line(module.doc_value())) }).unwrap_or(String::new()); - let mut crate_data = BTreeMap::new(); - crate_data.insert("doc".to_owned(), Json::String(crate_doc)); - crate_data.insert("i".to_owned(), Json::Array(crate_items)); - crate_data.insert("p".to_owned(), Json::Array(crate_paths)); + #[derive(Serialize)] + struct CrateData<'a> { + doc: String, + #[serde(rename = "i")] + items: Vec<&'a IndexItem>, + #[serde(rename = "p")] + paths: Vec<(ItemType, String)>, + } // Collect the index into a string - format!("searchIndex[{}] = {};", - as_json(&krate.name), - Json::Object(crate_data)) + format!( + r#"searchIndex["{}"] = {};"#, + krate.name, + serde_json::to_string(&CrateData { + doc: crate_doc, + items: crate_items, + paths: crate_paths, + }) + .unwrap() + ) } fn get_index_search_type(item: &clean::Item) -> Option<IndexItemFunctionType> { diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index a4be3dee938..a7ef428bc85 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -35,7 +35,6 @@ extern crate rustc_parse; extern crate rustc_target; extern crate rustc_typeck; extern crate rustc_lexer; -extern crate serialize; extern crate syntax; extern crate syntax_expand; extern crate syntax_pos; diff --git a/src/libstd/sys/sgx/abi/entry.S b/src/libstd/sys/sgx/abi/entry.S index cd26c7ca200..a3e059e8131 100644 --- a/src/libstd/sys/sgx/abi/entry.S +++ b/src/libstd/sys/sgx/abi/entry.S @@ -104,6 +104,36 @@ IMAGE_BASE: and %gs:tcsls_flags,%\reg .endm +/* We place the ELF entry point in a separate section so it can be removed by + elf2sgxs */ +.section .text_no_sgx, "ax" +.Lelf_entry_error_msg: + .ascii "Error: This file is an SGX enclave which cannot be executed as a standard Linux binary.\nSee the installation guide at https://edp.fortanix.com/docs/installation/guide/ on how to use 'cargo run' or follow the steps at https://edp.fortanix.com/docs/tasks/deployment/ for manual deployment.\n" +.Lelf_entry_error_msg_end: + +.global elf_entry +.type elf_entry,function +elf_entry: +/* print error message */ + movq $2,%rdi /* write to stderr (fd 2) */ + lea .Lelf_entry_error_msg(%rip),%rsi + movq $.Lelf_entry_error_msg_end-.Lelf_entry_error_msg,%rdx +.Lelf_entry_call: + movq $1,%rax /* write() syscall */ + syscall + test %rax,%rax + jle .Lelf_exit /* exit on error */ + add %rax,%rsi + sub %rax,%rdx /* all chars written? */ + jnz .Lelf_entry_call + +.Lelf_exit: + movq $60,%rax /* exit() syscall */ + movq $1,%rdi /* exit code 1 */ + syscall + ud2 /* should not be reached */ +/* end elf_entry */ + .text .global sgx_entry .type sgx_entry,function diff --git a/src/rustc/Cargo.toml b/src/rustc/Cargo.toml index 997d1393837..86a93d7d0cb 100644 --- a/src/rustc/Cargo.toml +++ b/src/rustc/Cargo.toml @@ -23,3 +23,4 @@ features = ['unprefixed_malloc_on_supported_platforms'] [features] jemalloc = ['jemalloc-sys'] +llvm = ['rustc_driver/llvm'] diff --git a/src/test/ui/associated-const/issue-63496.rs b/src/test/ui/associated-const/issue-63496.rs index 311c48b5e48..f9f663af5e2 100644 --- a/src/test/ui/associated-const/issue-63496.rs +++ b/src/test/ui/associated-const/issue-63496.rs @@ -2,8 +2,8 @@ trait A { const C: usize; fn f() -> ([u8; A::C], [u8; A::C]); - //~^ ERROR: type annotations needed: cannot resolve - //~| ERROR: type annotations needed: cannot resolve + //~^ ERROR: type annotations needed + //~| ERROR: type annotations needed } fn main() {} diff --git a/src/test/ui/associated-const/issue-63496.stderr b/src/test/ui/associated-const/issue-63496.stderr index 70bb12de1fb..23916a3ba44 100644 --- a/src/test/ui/associated-const/issue-63496.stderr +++ b/src/test/ui/associated-const/issue-63496.stderr @@ -1,20 +1,24 @@ -error[E0283]: type annotations needed: cannot resolve `_: A` +error[E0283]: type annotations needed --> $DIR/issue-63496.rs:4:21 | LL | const C: usize; | --------------- required by `A::C` LL | LL | fn f() -> ([u8; A::C], [u8; A::C]); - | ^^^^ + | ^^^^ cannot infer type + | + = note: cannot resolve `_: A` -error[E0283]: type annotations needed: cannot resolve `_: A` +error[E0283]: type annotations needed --> $DIR/issue-63496.rs:4:33 | LL | const C: usize; | --------------- required by `A::C` LL | LL | fn f() -> ([u8; A::C], [u8; A::C]); - | ^^^^ + | ^^^^ cannot infer type + | + = note: cannot resolve `_: A` error: aborting due to 2 previous errors diff --git a/src/test/ui/associated-item/issue-48027.stderr b/src/test/ui/associated-item/issue-48027.stderr index 562146a426d..9c825d593d3 100644 --- a/src/test/ui/associated-item/issue-48027.stderr +++ b/src/test/ui/associated-item/issue-48027.stderr @@ -7,13 +7,15 @@ LL | const X: usize; LL | impl dyn Bar {} | ^^^^^^^ the trait `Bar` cannot be made into an object -error[E0283]: type annotations needed: cannot resolve `_: Bar` +error[E0283]: type annotations needed --> $DIR/issue-48027.rs:3:32 | LL | const X: usize; | --------------- required by `Bar::X` LL | fn return_n(&self) -> [u8; Bar::X]; - | ^^^^^^ + | ^^^^^^ cannot infer type + | + = note: cannot resolve `_: Bar` error: aborting due to 2 previous errors diff --git a/src/test/ui/associated-types/associated-types-overridden-binding.stderr b/src/test/ui/associated-types/associated-types-overridden-binding.stderr index 5ef1b23cbcd..069da955b67 100644 --- a/src/test/ui/associated-types/associated-types-overridden-binding.stderr +++ b/src/test/ui/associated-types/associated-types-overridden-binding.stderr @@ -1,18 +1,23 @@ -error[E0284]: type annotations needed: cannot resolve `<Self as std::iter::Iterator>::Item == i32` +error[E0284]: type annotations needed --> $DIR/associated-types-overridden-binding.rs:4:1 | LL | trait Foo: Iterator<Item = i32> {} | ------------------------------- required by `Foo` LL | trait Bar: Foo<Item = u32> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `Self` + | + = note: cannot resolve `<Self as std::iter::Iterator>::Item == i32` -error[E0282]: type annotations needed +error[E0284]: type annotations needed --> $DIR/associated-types-overridden-binding.rs:7:1 | +LL | trait I32Iterator = Iterator<Item = i32>; + | ----------------------------------------- required by `I32Iterator` LL | trait U32Iterator = I32Iterator<Item = u32>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `Self` + | + = note: cannot resolve `<Self as std::iter::Iterator>::Item == i32` error: aborting due to 2 previous errors -Some errors have detailed explanations: E0282, E0284. -For more information about an error, try `rustc --explain E0282`. +For more information about this error, try `rustc --explain E0284`. diff --git a/src/test/ui/associated-types/associated-types-unconstrained.stderr b/src/test/ui/associated-types/associated-types-unconstrained.stderr index 4e9e54d3688..14ce4836f97 100644 --- a/src/test/ui/associated-types/associated-types-unconstrained.stderr +++ b/src/test/ui/associated-types/associated-types-unconstrained.stderr @@ -1,8 +1,10 @@ -error[E0284]: type annotations needed: cannot resolve `<_ as Foo>::A == _` +error[E0284]: type annotations needed --> $DIR/associated-types-unconstrained.rs:14:20 | LL | let x: isize = Foo::bar(); - | ^^^^^^^^ + | ^^^^^^^^ cannot infer type + | + = note: cannot resolve `<_ as Foo>::A == _` error: aborting due to previous error diff --git a/src/test/ui/async-await/unresolved_type_param.rs b/src/test/ui/async-await/unresolved_type_param.rs index 2876f9fea0e..79c043b701d 100644 --- a/src/test/ui/async-await/unresolved_type_param.rs +++ b/src/test/ui/async-await/unresolved_type_param.rs @@ -8,7 +8,7 @@ async fn bar<T>() -> () {} async fn foo() { bar().await; //~^ ERROR type inside `async fn` body must be known in this context - //~| NOTE cannot infer type for `T` + //~| NOTE cannot infer type for type parameter `T` //~| NOTE the type is part of the `async fn` body because of this `await` //~| NOTE in this expansion of desugaring of `await` } diff --git a/src/test/ui/async-await/unresolved_type_param.stderr b/src/test/ui/async-await/unresolved_type_param.stderr index c7866fc7744..b9b4f5133b9 100644 --- a/src/test/ui/async-await/unresolved_type_param.stderr +++ b/src/test/ui/async-await/unresolved_type_param.stderr @@ -2,7 +2,7 @@ error[E0698]: type inside `async fn` body must be known in this context --> $DIR/unresolved_type_param.rs:9:5 | LL | bar().await; - | ^^^ cannot infer type for `T` + | ^^^ cannot infer type for type parameter `T` | note: the type is part of the `async fn` body because of this `await` --> $DIR/unresolved_type_param.rs:9:5 diff --git a/src/test/ui/const-generics/cannot-infer-const-args.stderr b/src/test/ui/const-generics/cannot-infer-const-args.stderr index 32adc63156a..8379cbd4908 100644 --- a/src/test/ui/const-generics/cannot-infer-const-args.stderr +++ b/src/test/ui/const-generics/cannot-infer-const-args.stderr @@ -10,7 +10,7 @@ error[E0282]: type annotations needed --> $DIR/cannot-infer-const-args.rs:9:5 | LL | foo(); - | ^^^ cannot infer type for `fn() -> usize {foo::<_: usize>}` + | ^^^ cannot infer type for fn item `fn() -> usize {foo::<_: usize>}` error: aborting due to previous error diff --git a/src/test/ui/const-generics/fn-const-param-infer.stderr b/src/test/ui/const-generics/fn-const-param-infer.stderr index 2d9b6edb8a2..9ccad7bcdd7 100644 --- a/src/test/ui/const-generics/fn-const-param-infer.stderr +++ b/src/test/ui/const-generics/fn-const-param-infer.stderr @@ -30,7 +30,7 @@ error[E0282]: type annotations needed --> $DIR/fn-const-param-infer.rs:22:23 | LL | let _ = Checked::<generic>; - | ^^^^^^^ cannot infer type for `T` + | ^^^^^^^ cannot infer type for type parameter `T` error[E0308]: mismatched types --> $DIR/fn-const-param-infer.rs:25:40 diff --git a/src/test/ui/consts/issue-64662.stderr b/src/test/ui/consts/issue-64662.stderr index b81daae330b..b3c673ec027 100644 --- a/src/test/ui/consts/issue-64662.stderr +++ b/src/test/ui/consts/issue-64662.stderr @@ -2,13 +2,13 @@ error[E0282]: type annotations needed --> $DIR/issue-64662.rs:2:9 | LL | A = foo(), - | ^^^ cannot infer type for `T` + | ^^^ cannot infer type for type parameter `T` error[E0282]: type annotations needed --> $DIR/issue-64662.rs:3:9 | LL | B = foo(), - | ^^^ cannot infer type for `T` + | ^^^ cannot infer type for type parameter `T` error: aborting due to 2 previous errors diff --git a/src/test/ui/error-codes/E0004-2.stderr b/src/test/ui/error-codes/E0004-2.stderr index db0a2b5a085..f5b41cd1cc0 100644 --- a/src/test/ui/error-codes/E0004-2.stderr +++ b/src/test/ui/error-codes/E0004-2.stderr @@ -1,8 +1,8 @@ -error[E0004]: non-exhaustive patterns: multiple patterns of type `std::option::Option<i32>` are not handled +error[E0004]: non-exhaustive patterns: `None` and `Some(_)` not covered --> $DIR/E0004-2.rs:4:11 | LL | match x { } - | ^ + | ^ patterns `None` and `Some(_)` not covered | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms diff --git a/src/test/ui/error-codes/E0283.stderr b/src/test/ui/error-codes/E0283.stderr index aba649d83ec..ae5b7c3ae8f 100644 --- a/src/test/ui/error-codes/E0283.stderr +++ b/src/test/ui/error-codes/E0283.stderr @@ -1,11 +1,13 @@ -error[E0283]: type annotations needed: cannot resolve `_: Generator` +error[E0283]: type annotations needed --> $DIR/E0283.rs:18:21 | LL | fn create() -> u32; | ------------------- required by `Generator::create` ... LL | let cont: u32 = Generator::create(); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ cannot infer type + | + = note: cannot resolve `_: Generator` error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0401.stderr b/src/test/ui/error-codes/E0401.stderr index 485b76a09a3..0adf982d71c 100644 --- a/src/test/ui/error-codes/E0401.stderr +++ b/src/test/ui/error-codes/E0401.stderr @@ -36,7 +36,7 @@ error[E0282]: type annotations needed --> $DIR/E0401.rs:11:5 | LL | bfnr(x); - | ^^^^ cannot infer type for `U` + | ^^^^ cannot infer type for type parameter `U` error: aborting due to 4 previous errors diff --git a/src/test/ui/issues/issue-12028.stderr b/src/test/ui/issues/issue-12028.stderr index ff92d01a69e..5f2dd729c73 100644 --- a/src/test/ui/issues/issue-12028.stderr +++ b/src/test/ui/issues/issue-12028.stderr @@ -1,8 +1,10 @@ -error[E0284]: type annotations needed: cannot resolve `<_ as StreamHasher>::S == <H as StreamHasher>::S` +error[E0284]: type annotations needed --> $DIR/issue-12028.rs:27:14 | LL | self.input_stream(&mut stream); - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^ cannot infer type for type parameter `H` + | + = note: cannot resolve `<_ as StreamHasher>::S == <H as StreamHasher>::S` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-16966.stderr b/src/test/ui/issues/issue-16966.stderr index 13e77fe3073..0d565af79b5 100644 --- a/src/test/ui/issues/issue-16966.stderr +++ b/src/test/ui/issues/issue-16966.stderr @@ -2,7 +2,7 @@ error[E0282]: type annotations needed --> $DIR/issue-16966.rs:2:5 | LL | panic!(std::default::Default::default()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for `M` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `M` | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) diff --git a/src/test/ui/issues/issue-17551.stderr b/src/test/ui/issues/issue-17551.stderr index ce16f0f58ea..5468268e7de 100644 --- a/src/test/ui/issues/issue-17551.stderr +++ b/src/test/ui/issues/issue-17551.stderr @@ -2,7 +2,7 @@ error[E0282]: type annotations needed for `B<T>` --> $DIR/issue-17551.rs:6:15 | LL | let foo = B(marker::PhantomData); - | --- ^ cannot infer type for `T` + | --- ^ cannot infer type for type parameter `T` | | | consider giving `foo` the explicit type `B<T>`, where the type parameter `T` is specified diff --git a/src/test/ui/issues/issue-21974.stderr b/src/test/ui/issues/issue-21974.stderr index 7ceb2bd23f6..b1536bd8ddb 100644 --- a/src/test/ui/issues/issue-21974.stderr +++ b/src/test/ui/issues/issue-21974.stderr @@ -1,4 +1,4 @@ -error[E0283]: type annotations needed: cannot resolve `&'a T: Foo` +error[E0283]: type annotations needed --> $DIR/issue-21974.rs:10:1 | LL | trait Foo { @@ -11,7 +11,9 @@ LL | | { LL | | x.foo(); LL | | y.foo(); LL | | } - | |_^ + | |_^ cannot infer type for reference `&'a T` + | + = note: cannot resolve `&'a T: Foo` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-24424.rs b/src/test/ui/issues/issue-24424.rs index 9b74cd1230e..22bf513afe8 100644 --- a/src/test/ui/issues/issue-24424.rs +++ b/src/test/ui/issues/issue-24424.rs @@ -2,6 +2,6 @@ trait Trait1<'l0, T0> {} trait Trait0<'l0> {} impl <'l0, 'l1, T0> Trait1<'l0, T0> for bool where T0 : Trait0<'l0>, T0 : Trait0<'l1> {} -//~^ ERROR type annotations needed: cannot resolve `T0: Trait0<'l0>` +//~^ ERROR type annotations needed fn main() {} diff --git a/src/test/ui/issues/issue-24424.stderr b/src/test/ui/issues/issue-24424.stderr index 8c539f7cedd..8f0850328b4 100644 --- a/src/test/ui/issues/issue-24424.stderr +++ b/src/test/ui/issues/issue-24424.stderr @@ -1,11 +1,13 @@ -error[E0283]: type annotations needed: cannot resolve `T0: Trait0<'l0>` +error[E0283]: type annotations needed --> $DIR/issue-24424.rs:4:1 | LL | trait Trait0<'l0> {} | ----------------- required by `Trait0` LL | LL | impl <'l0, 'l1, T0> Trait1<'l0, T0> for bool where T0 : Trait0<'l0>, T0 : Trait0<'l1> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T0` + | + = note: cannot resolve `T0: Trait0<'l0>` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-25368.stderr b/src/test/ui/issues/issue-25368.stderr index 0b890b573da..de020d4b56b 100644 --- a/src/test/ui/issues/issue-25368.stderr +++ b/src/test/ui/issues/issue-25368.stderr @@ -5,7 +5,7 @@ LL | let (tx, rx) = channel(); | -------- consider giving this pattern the explicit type `(std::sync::mpsc::Sender<Foo<T>>, std::sync::mpsc::Receiver<Foo<T>>)`, where the type parameter `T` is specified ... LL | tx.send(Foo{ foo: PhantomData }); - | ^^^ cannot infer type for `T` + | ^^^ cannot infer type for type parameter `T` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-29147.rs b/src/test/ui/issues/issue-29147.rs index 7ec96b97eef..271bc526033 100644 --- a/src/test/ui/issues/issue-29147.rs +++ b/src/test/ui/issues/issue-29147.rs @@ -18,5 +18,5 @@ impl Foo for S5<u32> { fn xxx(&self) {} } impl Foo for S5<u64> { fn xxx(&self) {} } fn main() { - let _ = <S5<_>>::xxx; //~ ERROR cannot resolve `S5<_>: Foo` + let _ = <S5<_>>::xxx; //~ ERROR type annotations needed } diff --git a/src/test/ui/issues/issue-29147.stderr b/src/test/ui/issues/issue-29147.stderr index c9dd92fca7d..1efedb45cac 100644 --- a/src/test/ui/issues/issue-29147.stderr +++ b/src/test/ui/issues/issue-29147.stderr @@ -1,11 +1,13 @@ -error[E0283]: type annotations needed: cannot resolve `S5<_>: Foo` +error[E0283]: type annotations needed --> $DIR/issue-29147.rs:21:13 | LL | trait Foo { fn xxx(&self); } | -------------- required by `Foo::xxx` ... LL | let _ = <S5<_>>::xxx; - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^ cannot infer type for struct `S5<_>` + | + = note: cannot resolve `S5<_>: Foo` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-3601.stderr b/src/test/ui/issues/issue-3601.stderr index fa0fa3345f5..445eb4107d1 100644 --- a/src/test/ui/issues/issue-3601.stderr +++ b/src/test/ui/issues/issue-3601.stderr @@ -1,8 +1,8 @@ -error[E0004]: non-exhaustive patterns: `_` not covered +error[E0004]: non-exhaustive patterns: `Box(_)` not covered --> $DIR/issue-3601.rs:30:44 | LL | box NodeKind::Element(ed) => match ed.kind { - | ^^^^^^^ pattern `_` not covered + | ^^^^^^^ pattern `Box(_)` not covered | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms diff --git a/src/test/ui/issues/issue-5062.stderr b/src/test/ui/issues/issue-5062.stderr index 0f5c6d8d4bf..a20118d6911 100644 --- a/src/test/ui/issues/issue-5062.stderr +++ b/src/test/ui/issues/issue-5062.stderr @@ -2,7 +2,7 @@ error[E0282]: type annotations needed --> $DIR/issue-5062.rs:1:29 | LL | fn main() { format!("{:?}", None); } - | ^^^^ cannot infer type for `T` + | ^^^^ cannot infer type for type parameter `T` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-54954.stderr b/src/test/ui/issues/issue-54954.stderr index 56ccdaf7aac..d99a5772e8a 100644 --- a/src/test/ui/issues/issue-54954.stderr +++ b/src/test/ui/issues/issue-54954.stderr @@ -4,14 +4,16 @@ error[E0379]: trait fns cannot be declared const LL | const fn const_val<T: Sized>() -> usize { | ^^^^^ trait fns cannot be const -error[E0283]: type annotations needed: cannot resolve `_: Tt` +error[E0283]: type annotations needed --> $DIR/issue-54954.rs:3:24 | LL | const ARR_LEN: usize = Tt::const_val::<[i8; 123]>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type ... LL | const fn const_val<T: Sized>() -> usize { | --------- - required by this bound in `Tt::const_val` + | + = note: cannot resolve `_: Tt` error[E0080]: evaluation of constant value failed --> $DIR/issue-54954.rs:13:15 diff --git a/src/test/ui/issues/issue-58022.rs b/src/test/ui/issues/issue-58022.rs index 30527903ed0..e4b9b3b53a6 100644 --- a/src/test/ui/issues/issue-58022.rs +++ b/src/test/ui/issues/issue-58022.rs @@ -2,7 +2,7 @@ pub trait Foo: Sized { const SIZE: usize; fn new(slice: &[u8; Foo::SIZE]) -> Self; - //~^ ERROR: type annotations needed: cannot resolve `_: Foo` + //~^ ERROR: type annotations needed } pub struct Bar<T: ?Sized>(T); diff --git a/src/test/ui/issues/issue-58022.stderr b/src/test/ui/issues/issue-58022.stderr index a3e4cb63202..ef0d66d7ad6 100644 --- a/src/test/ui/issues/issue-58022.stderr +++ b/src/test/ui/issues/issue-58022.stderr @@ -4,14 +4,16 @@ error[E0423]: expected function, tuple struct or tuple variant, found trait `Foo LL | Foo(Box::new(*slice)) | ^^^ not a function, tuple struct or tuple variant -error[E0283]: type annotations needed: cannot resolve `_: Foo` +error[E0283]: type annotations needed --> $DIR/issue-58022.rs:4:25 | LL | const SIZE: usize; | ------------------ required by `Foo::SIZE` LL | LL | fn new(slice: &[u8; Foo::SIZE]) -> Self; - | ^^^^^^^^^ + | ^^^^^^^^^ cannot infer type + | + = note: cannot resolve `_: Foo` error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-6458-2.stderr b/src/test/ui/issues/issue-6458-2.stderr index b5da2bf096c..d538a69045f 100644 --- a/src/test/ui/issues/issue-6458-2.stderr +++ b/src/test/ui/issues/issue-6458-2.stderr @@ -2,7 +2,7 @@ error[E0282]: type annotations needed --> $DIR/issue-6458-2.rs:3:21 | LL | format!("{:?}", None); - | ^^^^ cannot infer type for `T` + | ^^^^ cannot infer type for type parameter `T` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-6458-3.stderr b/src/test/ui/issues/issue-6458-3.stderr index 784497c959d..6b3f469ee37 100644 --- a/src/test/ui/issues/issue-6458-3.stderr +++ b/src/test/ui/issues/issue-6458-3.stderr @@ -2,7 +2,7 @@ error[E0282]: type annotations needed --> $DIR/issue-6458-3.rs:4:5 | LL | mem::transmute(0); - | ^^^^^^^^^^^^^^ cannot infer type for `U` + | ^^^^^^^^^^^^^^ cannot infer type for type parameter `U` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-6458.stderr b/src/test/ui/issues/issue-6458.stderr index d59d872ba93..de315659b6d 100644 --- a/src/test/ui/issues/issue-6458.stderr +++ b/src/test/ui/issues/issue-6458.stderr @@ -2,7 +2,7 @@ error[E0282]: type annotations needed --> $DIR/issue-6458.rs:9:4 | LL | foo(TypeWithState(marker::PhantomData)); - | ^^^ cannot infer type for `State` + | ^^^ cannot infer type for type parameter `State` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-65611.stderr b/src/test/ui/issues/issue-65611.stderr index cb441c13c6b..20e2ba144d9 100644 --- a/src/test/ui/issues/issue-65611.stderr +++ b/src/test/ui/issues/issue-65611.stderr @@ -2,7 +2,10 @@ error[E0282]: type annotations needed --> $DIR/issue-65611.rs:59:20 | LL | let x = buffer.last().unwrap().0.clone(); - | ^^^^ cannot infer type for `T` + | -------^^^^-- + | | | + | | cannot infer type for type parameter `T` + | this method call resolves to `std::option::Option<&T>` | = note: type must be known at this point diff --git a/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr b/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr index fcd97647568..f3f3c476809 100644 --- a/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr +++ b/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr @@ -2,7 +2,7 @@ error[E0282]: type annotations needed for `std::vec::Vec<T>` --> $DIR/method-ambig-one-trait-unknown-int-type.rs:24:17 | LL | let mut x = Vec::new(); - | ----- ^^^^^^^^ cannot infer type for `T` + | ----- ^^^^^^^^ cannot infer type for type parameter `T` | | | consider giving `x` the explicit type `std::vec::Vec<T>`, where the type parameter `T` is specified diff --git a/src/test/ui/missing/missing-items/missing-type-parameter.stderr b/src/test/ui/missing/missing-items/missing-type-parameter.stderr index dbb467d60f9..be97f2373c3 100644 --- a/src/test/ui/missing/missing-items/missing-type-parameter.stderr +++ b/src/test/ui/missing/missing-items/missing-type-parameter.stderr @@ -2,7 +2,7 @@ error[E0282]: type annotations needed --> $DIR/missing-type-parameter.rs:4:5 | LL | foo(); - | ^^^ cannot infer type for `X` + | ^^^ cannot infer type for type parameter `X` error: aborting due to previous error diff --git a/src/test/ui/pattern/usefulness/always-inhabited-union-ref.stderr b/src/test/ui/pattern/usefulness/always-inhabited-union-ref.stderr index 792ab6f59a4..1b1096c977a 100644 --- a/src/test/ui/pattern/usefulness/always-inhabited-union-ref.stderr +++ b/src/test/ui/pattern/usefulness/always-inhabited-union-ref.stderr @@ -9,8 +9,13 @@ LL | match uninhab_ref() { error[E0004]: non-exhaustive patterns: type `Foo` is non-empty --> $DIR/always-inhabited-union-ref.rs:27:11 | -LL | match uninhab_union() { - | ^^^^^^^^^^^^^^^ +LL | / pub union Foo { +LL | | foo: !, +LL | | } + | |_- `Foo` defined here +... +LL | match uninhab_union() { + | ^^^^^^^^^^^^^^^ | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms diff --git a/src/test/ui/pattern/usefulness/match-empty-exhaustive_patterns.rs b/src/test/ui/pattern/usefulness/match-empty-exhaustive_patterns.rs new file mode 100644 index 00000000000..57b6b910ca1 --- /dev/null +++ b/src/test/ui/pattern/usefulness/match-empty-exhaustive_patterns.rs @@ -0,0 +1,93 @@ +#![feature(never_type)] +#![feature(exhaustive_patterns)] +#![deny(unreachable_patterns)] +enum Foo {} + +struct NonEmptyStruct(bool); //~ `NonEmptyStruct` defined here +union NonEmptyUnion1 { //~ `NonEmptyUnion1` defined here + foo: (), +} +union NonEmptyUnion2 { //~ `NonEmptyUnion2` defined here + foo: (), + bar: (), +} +enum NonEmptyEnum1 { //~ `NonEmptyEnum1` defined here + Foo(bool), + //~^ not covered + //~| not covered +} +enum NonEmptyEnum2 { //~ `NonEmptyEnum2` defined here + Foo(bool), + //~^ not covered + //~| not covered + Bar, + //~^ not covered + //~| not covered +} +enum NonEmptyEnum5 { //~ `NonEmptyEnum5` defined here + V1, V2, V3, V4, V5, +} + +macro_rules! match_empty { + ($e:expr) => { + match $e {} + }; +} +macro_rules! match_false { + ($e:expr) => { + match $e { + _ if false => {} + } + }; +} + +fn foo(x: Foo) { + match_empty!(x); // ok + match x { + _ => {}, //~ ERROR unreachable pattern + } + match x { + _ if false => {}, //~ ERROR unreachable pattern + } +} + +fn main() { + match None::<!> { + None => {} + Some(_) => {} //~ ERROR unreachable pattern + } + match None::<Foo> { + None => {} + Some(_) => {} //~ ERROR unreachable pattern + } + + match_empty!(0u8); + //~^ ERROR type `u8` is non-empty + match_empty!(NonEmptyStruct(true)); + //~^ ERROR type `NonEmptyStruct` is non-empty + match_empty!((NonEmptyUnion1 { foo: () })); + //~^ ERROR type `NonEmptyUnion1` is non-empty + match_empty!((NonEmptyUnion2 { foo: () })); + //~^ ERROR type `NonEmptyUnion2` is non-empty + match_empty!(NonEmptyEnum1::Foo(true)); + //~^ ERROR `Foo(_)` not covered + match_empty!(NonEmptyEnum2::Foo(true)); + //~^ ERROR `Foo(_)` and `Bar` not covered + match_empty!(NonEmptyEnum5::V1); + //~^ ERROR `V1`, `V2`, `V3` and 2 more not covered + + match_false!(0u8); + //~^ ERROR `_` not covered + match_false!(NonEmptyStruct(true)); + //~^ ERROR `NonEmptyStruct(_)` not covered + match_false!((NonEmptyUnion1 { foo: () })); + //~^ ERROR `NonEmptyUnion1 { .. }` not covered + match_false!((NonEmptyUnion2 { foo: () })); + //~^ ERROR `NonEmptyUnion2 { .. }` not covered + match_false!(NonEmptyEnum1::Foo(true)); + //~^ ERROR `Foo(_)` not covered + match_false!(NonEmptyEnum2::Foo(true)); + //~^ ERROR `Foo(_)` and `Bar` not covered + match_false!(NonEmptyEnum5::V1); + //~^ ERROR `V1`, `V2`, `V3` and 2 more not covered +} diff --git a/src/test/ui/pattern/usefulness/match-empty-exhaustive_patterns.stderr b/src/test/ui/pattern/usefulness/match-empty-exhaustive_patterns.stderr new file mode 100644 index 00000000000..f242ecf2dae --- /dev/null +++ b/src/test/ui/pattern/usefulness/match-empty-exhaustive_patterns.stderr @@ -0,0 +1,223 @@ +error: unreachable pattern + --> $DIR/match-empty-exhaustive_patterns.rs:47:9 + | +LL | _ => {}, + | ^ + | +note: lint level defined here + --> $DIR/match-empty-exhaustive_patterns.rs:3:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/match-empty-exhaustive_patterns.rs:50:9 + | +LL | _ if false => {}, + | ^ + +error: unreachable pattern + --> $DIR/match-empty-exhaustive_patterns.rs:57:9 + | +LL | Some(_) => {} + | ^^^^^^^ + +error: unreachable pattern + --> $DIR/match-empty-exhaustive_patterns.rs:61:9 + | +LL | Some(_) => {} + | ^^^^^^^ + +error[E0004]: non-exhaustive patterns: type `u8` is non-empty + --> $DIR/match-empty-exhaustive_patterns.rs:64:18 + | +LL | match_empty!(0u8); + | ^^^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: type `NonEmptyStruct` is non-empty + --> $DIR/match-empty-exhaustive_patterns.rs:66:18 + | +LL | struct NonEmptyStruct(bool); + | ---------------------------- `NonEmptyStruct` defined here +... +LL | match_empty!(NonEmptyStruct(true)); + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty + --> $DIR/match-empty-exhaustive_patterns.rs:68:18 + | +LL | / union NonEmptyUnion1 { +LL | | foo: (), +LL | | } + | |_- `NonEmptyUnion1` defined here +... +LL | match_empty!((NonEmptyUnion1 { foo: () })); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty + --> $DIR/match-empty-exhaustive_patterns.rs:70:18 + | +LL | / union NonEmptyUnion2 { +LL | | foo: (), +LL | | bar: (), +LL | | } + | |_- `NonEmptyUnion2` defined here +... +LL | match_empty!((NonEmptyUnion2 { foo: () })); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `Foo(_)` not covered + --> $DIR/match-empty-exhaustive_patterns.rs:72:18 + | +LL | / enum NonEmptyEnum1 { +LL | | Foo(bool), + | | --- not covered +LL | | +LL | | +LL | | } + | |_- `NonEmptyEnum1` defined here +... +LL | match_empty!(NonEmptyEnum1::Foo(true)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo(_)` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `Foo(_)` and `Bar` not covered + --> $DIR/match-empty-exhaustive_patterns.rs:74:18 + | +LL | / enum NonEmptyEnum2 { +LL | | Foo(bool), + | | --- not covered +LL | | +LL | | +LL | | Bar, + | | --- not covered +LL | | +LL | | +LL | | } + | |_- `NonEmptyEnum2` defined here +... +LL | match_empty!(NonEmptyEnum2::Foo(true)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `Foo(_)` and `Bar` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `V1`, `V2`, `V3` and 2 more not covered + --> $DIR/match-empty-exhaustive_patterns.rs:76:18 + | +LL | / enum NonEmptyEnum5 { +LL | | V1, V2, V3, V4, V5, +LL | | } + | |_- `NonEmptyEnum5` defined here +... +LL | match_empty!(NonEmptyEnum5::V1); + | ^^^^^^^^^^^^^^^^^ patterns `V1`, `V2`, `V3` and 2 more not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/match-empty-exhaustive_patterns.rs:79:18 + | +LL | match_false!(0u8); + | ^^^ pattern `_` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `NonEmptyStruct(_)` not covered + --> $DIR/match-empty-exhaustive_patterns.rs:81:18 + | +LL | struct NonEmptyStruct(bool); + | ---------------------------- `NonEmptyStruct` defined here +... +LL | match_false!(NonEmptyStruct(true)); + | ^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct(_)` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered + --> $DIR/match-empty-exhaustive_patterns.rs:83:18 + | +LL | / union NonEmptyUnion1 { +LL | | foo: (), +LL | | } + | |_- `NonEmptyUnion1` defined here +... +LL | match_false!((NonEmptyUnion1 { foo: () })); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered + --> $DIR/match-empty-exhaustive_patterns.rs:85:18 + | +LL | / union NonEmptyUnion2 { +LL | | foo: (), +LL | | bar: (), +LL | | } + | |_- `NonEmptyUnion2` defined here +... +LL | match_false!((NonEmptyUnion2 { foo: () })); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `Foo(_)` not covered + --> $DIR/match-empty-exhaustive_patterns.rs:87:18 + | +LL | / enum NonEmptyEnum1 { +LL | | Foo(bool), + | | --- not covered +LL | | +LL | | +LL | | } + | |_- `NonEmptyEnum1` defined here +... +LL | match_false!(NonEmptyEnum1::Foo(true)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo(_)` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `Foo(_)` and `Bar` not covered + --> $DIR/match-empty-exhaustive_patterns.rs:89:18 + | +LL | / enum NonEmptyEnum2 { +LL | | Foo(bool), + | | --- not covered +LL | | +LL | | +LL | | Bar, + | | --- not covered +LL | | +LL | | +LL | | } + | |_- `NonEmptyEnum2` defined here +... +LL | match_false!(NonEmptyEnum2::Foo(true)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `Foo(_)` and `Bar` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `V1`, `V2`, `V3` and 2 more not covered + --> $DIR/match-empty-exhaustive_patterns.rs:91:18 + | +LL | / enum NonEmptyEnum5 { +LL | | V1, V2, V3, V4, V5, +LL | | } + | |_- `NonEmptyEnum5` defined here +... +LL | match_false!(NonEmptyEnum5::V1); + | ^^^^^^^^^^^^^^^^^ patterns `V1`, `V2`, `V3` and 2 more not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error: aborting due to 18 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/pattern/usefulness/match-empty.rs b/src/test/ui/pattern/usefulness/match-empty.rs new file mode 100644 index 00000000000..f7577125d8a --- /dev/null +++ b/src/test/ui/pattern/usefulness/match-empty.rs @@ -0,0 +1,92 @@ +#![feature(never_type)] +#![deny(unreachable_patterns)] +enum Foo {} + +struct NonEmptyStruct(bool); //~ `NonEmptyStruct` defined here +union NonEmptyUnion1 { //~ `NonEmptyUnion1` defined here + foo: (), +} +union NonEmptyUnion2 { //~ `NonEmptyUnion2` defined here + foo: (), + bar: (), +} +enum NonEmptyEnum1 { //~ `NonEmptyEnum1` defined here + Foo(bool), + //~^ not covered + //~| not covered +} +enum NonEmptyEnum2 { //~ `NonEmptyEnum2` defined here + Foo(bool), + //~^ not covered + //~| not covered + Bar, + //~^ not covered + //~| not covered +} +enum NonEmptyEnum5 { //~ `NonEmptyEnum5` defined here + V1, V2, V3, V4, V5, +} + +macro_rules! match_empty { + ($e:expr) => { + match $e {} + }; +} +macro_rules! match_false { + ($e:expr) => { + match $e { + _ if false => {} + } + }; +} + +fn foo(x: Foo) { + match_empty!(x); // ok + match_false!(x); // Not detected as unreachable nor exhaustive. + //~^ ERROR non-exhaustive patterns: `_` not covered + match x { + _ => {}, // Not detected as unreachable, see #55123. + } +} + +fn main() { + // `exhaustive_patterns` is not on, so uninhabited branches are not detected as unreachable. + match None::<!> { + None => {} + Some(_) => {} + } + match None::<Foo> { + None => {} + Some(_) => {} + } + + match_empty!(0u8); + //~^ ERROR type `u8` is non-empty + match_empty!(NonEmptyStruct(true)); + //~^ ERROR type `NonEmptyStruct` is non-empty + match_empty!((NonEmptyUnion1 { foo: () })); + //~^ ERROR type `NonEmptyUnion1` is non-empty + match_empty!((NonEmptyUnion2 { foo: () })); + //~^ ERROR type `NonEmptyUnion2` is non-empty + match_empty!(NonEmptyEnum1::Foo(true)); + //~^ ERROR `Foo(_)` not covered + match_empty!(NonEmptyEnum2::Foo(true)); + //~^ ERROR `Foo(_)` and `Bar` not covered + match_empty!(NonEmptyEnum5::V1); + //~^ ERROR `V1`, `V2`, `V3` and 2 more not covered + + match_false!(0u8); + //~^ ERROR `_` not covered + match_false!(NonEmptyStruct(true)); + //~^ ERROR `NonEmptyStruct(_)` not covered + match_false!((NonEmptyUnion1 { foo: () })); + //~^ ERROR `NonEmptyUnion1 { .. }` not covered + match_false!((NonEmptyUnion2 { foo: () })); + //~^ ERROR `NonEmptyUnion2 { .. }` not covered + match_false!(NonEmptyEnum1::Foo(true)); + //~^ ERROR `Foo(_)` not covered + match_false!(NonEmptyEnum2::Foo(true)); + //~^ ERROR `Foo(_)` and `Bar` not covered + match_false!(NonEmptyEnum5::V1); + //~^ ERROR `V1`, `V2`, `V3` and 2 more not covered +} diff --git a/src/test/ui/pattern/usefulness/match-empty.stderr b/src/test/ui/pattern/usefulness/match-empty.stderr new file mode 100644 index 00000000000..72e3fc0a167 --- /dev/null +++ b/src/test/ui/pattern/usefulness/match-empty.stderr @@ -0,0 +1,204 @@ +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/match-empty.rs:45:18 + | +LL | enum Foo {} + | ----------- `Foo` defined here +... +LL | match_false!(x); // Not detected as unreachable nor exhaustive. + | ^ pattern `_` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: type `u8` is non-empty + --> $DIR/match-empty.rs:63:18 + | +LL | match_empty!(0u8); + | ^^^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: type `NonEmptyStruct` is non-empty + --> $DIR/match-empty.rs:65:18 + | +LL | struct NonEmptyStruct(bool); + | ---------------------------- `NonEmptyStruct` defined here +... +LL | match_empty!(NonEmptyStruct(true)); + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty + --> $DIR/match-empty.rs:67:18 + | +LL | / union NonEmptyUnion1 { +LL | | foo: (), +LL | | } + | |_- `NonEmptyUnion1` defined here +... +LL | match_empty!((NonEmptyUnion1 { foo: () })); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty + --> $DIR/match-empty.rs:69:18 + | +LL | / union NonEmptyUnion2 { +LL | | foo: (), +LL | | bar: (), +LL | | } + | |_- `NonEmptyUnion2` defined here +... +LL | match_empty!((NonEmptyUnion2 { foo: () })); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `Foo(_)` not covered + --> $DIR/match-empty.rs:71:18 + | +LL | / enum NonEmptyEnum1 { +LL | | Foo(bool), + | | --- not covered +LL | | +LL | | +LL | | } + | |_- `NonEmptyEnum1` defined here +... +LL | match_empty!(NonEmptyEnum1::Foo(true)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo(_)` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `Foo(_)` and `Bar` not covered + --> $DIR/match-empty.rs:73:18 + | +LL | / enum NonEmptyEnum2 { +LL | | Foo(bool), + | | --- not covered +LL | | +LL | | +LL | | Bar, + | | --- not covered +LL | | +LL | | +LL | | } + | |_- `NonEmptyEnum2` defined here +... +LL | match_empty!(NonEmptyEnum2::Foo(true)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `Foo(_)` and `Bar` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `V1`, `V2`, `V3` and 2 more not covered + --> $DIR/match-empty.rs:75:18 + | +LL | / enum NonEmptyEnum5 { +LL | | V1, V2, V3, V4, V5, +LL | | } + | |_- `NonEmptyEnum5` defined here +... +LL | match_empty!(NonEmptyEnum5::V1); + | ^^^^^^^^^^^^^^^^^ patterns `V1`, `V2`, `V3` and 2 more not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/match-empty.rs:78:18 + | +LL | match_false!(0u8); + | ^^^ pattern `_` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `NonEmptyStruct(_)` not covered + --> $DIR/match-empty.rs:80:18 + | +LL | struct NonEmptyStruct(bool); + | ---------------------------- `NonEmptyStruct` defined here +... +LL | match_false!(NonEmptyStruct(true)); + | ^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct(_)` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered + --> $DIR/match-empty.rs:82:18 + | +LL | / union NonEmptyUnion1 { +LL | | foo: (), +LL | | } + | |_- `NonEmptyUnion1` defined here +... +LL | match_false!((NonEmptyUnion1 { foo: () })); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered + --> $DIR/match-empty.rs:84:18 + | +LL | / union NonEmptyUnion2 { +LL | | foo: (), +LL | | bar: (), +LL | | } + | |_- `NonEmptyUnion2` defined here +... +LL | match_false!((NonEmptyUnion2 { foo: () })); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `Foo(_)` not covered + --> $DIR/match-empty.rs:86:18 + | +LL | / enum NonEmptyEnum1 { +LL | | Foo(bool), + | | --- not covered +LL | | +LL | | +LL | | } + | |_- `NonEmptyEnum1` defined here +... +LL | match_false!(NonEmptyEnum1::Foo(true)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `Foo(_)` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `Foo(_)` and `Bar` not covered + --> $DIR/match-empty.rs:88:18 + | +LL | / enum NonEmptyEnum2 { +LL | | Foo(bool), + | | --- not covered +LL | | +LL | | +LL | | Bar, + | | --- not covered +LL | | +LL | | +LL | | } + | |_- `NonEmptyEnum2` defined here +... +LL | match_false!(NonEmptyEnum2::Foo(true)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `Foo(_)` and `Bar` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `V1`, `V2`, `V3` and 2 more not covered + --> $DIR/match-empty.rs:90:18 + | +LL | / enum NonEmptyEnum5 { +LL | | V1, V2, V3, V4, V5, +LL | | } + | |_- `NonEmptyEnum5` defined here +... +LL | match_false!(NonEmptyEnum5::V1); + | ^^^^^^^^^^^^^^^^^ patterns `V1`, `V2`, `V3` and 2 more not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error: aborting due to 15 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/question-mark-type-infer.rs b/src/test/ui/question-mark-type-infer.rs index 95ee01a70ce..2ef8618192f 100644 --- a/src/test/ui/question-mark-type-infer.rs +++ b/src/test/ui/question-mark-type-infer.rs @@ -9,7 +9,7 @@ fn f(x: &i32) -> Result<i32, ()> { fn g() -> Result<Vec<i32>, ()> { let l = [1, 2, 3, 4]; - l.iter().map(f).collect()? //~ ERROR type annotations needed: cannot resolve + l.iter().map(f).collect()? //~ ERROR type annotations needed } fn main() { diff --git a/src/test/ui/question-mark-type-infer.stderr b/src/test/ui/question-mark-type-infer.stderr index 53a170e7d43..7911701946c 100644 --- a/src/test/ui/question-mark-type-infer.stderr +++ b/src/test/ui/question-mark-type-infer.stderr @@ -1,8 +1,13 @@ -error[E0284]: type annotations needed: cannot resolve `<_ as std::ops::Try>::Ok == _` - --> $DIR/question-mark-type-infer.rs:12:5 +error[E0284]: type annotations needed + --> $DIR/question-mark-type-infer.rs:12:21 | LL | l.iter().map(f).collect()? - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^ + | | + | cannot infer type + | help: consider specifying the type argument in the method call: `collect::<B>` + | + = note: cannot resolve `<_ as std::ops::Try>::Ok == _` error: aborting due to previous error diff --git a/src/test/ui/rfc-2008-non-exhaustive/auxiliary/enums.rs b/src/test/ui/rfc-2008-non-exhaustive/auxiliary/enums.rs index bbc25d40256..8516bafef9b 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/auxiliary/enums.rs +++ b/src/test/ui/rfc-2008-non-exhaustive/auxiliary/enums.rs @@ -6,3 +6,6 @@ pub enum NonExhaustiveEnum { Tuple(u32), Struct { field: u32 } } + +#[non_exhaustive] +pub enum EmptyNonExhaustiveEnum {} diff --git a/src/test/ui/rfc-2008-non-exhaustive/enum.rs b/src/test/ui/rfc-2008-non-exhaustive/enum.rs index 7423a970e2e..802f20b4bed 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/enum.rs +++ b/src/test/ui/rfc-2008-non-exhaustive/enum.rs @@ -1,7 +1,14 @@ // aux-build:enums.rs extern crate enums; -use enums::NonExhaustiveEnum; +use enums::{EmptyNonExhaustiveEnum, NonExhaustiveEnum}; + +fn empty(x: EmptyNonExhaustiveEnum) { + match x {} //~ ERROR type `enums::EmptyNonExhaustiveEnum` is non-empty + match x { + _ => {}, // ok + } +} fn main() { let enum_unit = NonExhaustiveEnum::Unit; @@ -13,6 +20,9 @@ fn main() { NonExhaustiveEnum::Struct { .. } => "third" }; + match enum_unit {}; + //~^ ERROR non-exhaustive patterns: `_` not covered [E0004] + // Everything below this is expected to compile successfully. let enum_unit = NonExhaustiveEnum::Unit; diff --git a/src/test/ui/rfc-2008-non-exhaustive/enum.stderr b/src/test/ui/rfc-2008-non-exhaustive/enum.stderr index b5c1a4ebba4..a2bdcbaa447 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/enum.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/enum.stderr @@ -1,11 +1,27 @@ +error[E0004]: non-exhaustive patterns: type `enums::EmptyNonExhaustiveEnum` is non-empty + --> $DIR/enum.rs:7:11 + | +LL | match x {} + | ^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + error[E0004]: non-exhaustive patterns: `_` not covered - --> $DIR/enum.rs:9:11 + --> $DIR/enum.rs:16:11 | LL | match enum_unit { | ^^^^^^^^^ pattern `_` not covered | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms -error: aborting due to previous error +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/enum.rs:23:11 + | +LL | match enum_unit {}; + | ^^^^^^^^^ pattern `_` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/rfc-2008-non-exhaustive/enum_same_crate_empty_match.rs b/src/test/ui/rfc-2008-non-exhaustive/enum_same_crate_empty_match.rs new file mode 100644 index 00000000000..afd6d996c15 --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/enum_same_crate_empty_match.rs @@ -0,0 +1,37 @@ +#![deny(unreachable_patterns)] + +#[non_exhaustive] +pub enum NonExhaustiveEnum { + Unit, + //~^ not covered + Tuple(u32), + //~^ not covered + Struct { field: u32 } + //~^ not covered +} + +pub enum NormalEnum { + Unit, + //~^ not covered + Tuple(u32), + //~^ not covered + Struct { field: u32 } + //~^ not covered +} + +#[non_exhaustive] +pub enum EmptyNonExhaustiveEnum {} + +fn empty_non_exhaustive(x: EmptyNonExhaustiveEnum) { + match x {} + match x { + _ => {} // not detected as unreachable + } +} + +fn main() { + match NonExhaustiveEnum::Unit {} + //~^ ERROR `Unit`, `Tuple(_)` and `Struct { .. }` not covered [E0004] + match NormalEnum::Unit {} + //~^ ERROR `Unit`, `Tuple(_)` and `Struct { .. }` not covered [E0004] +} diff --git a/src/test/ui/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr b/src/test/ui/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr new file mode 100644 index 00000000000..a99a690bc9e --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/enum_same_crate_empty_match.stderr @@ -0,0 +1,45 @@ +error[E0004]: non-exhaustive patterns: `Unit`, `Tuple(_)` and `Struct { .. }` not covered + --> $DIR/enum_same_crate_empty_match.rs:33:11 + | +LL | / pub enum NonExhaustiveEnum { +LL | | Unit, + | | ---- not covered +LL | | +LL | | Tuple(u32), + | | ----- not covered +LL | | +LL | | Struct { field: u32 } + | | ------ not covered +LL | | +LL | | } + | |_- `NonExhaustiveEnum` defined here +... +LL | match NonExhaustiveEnum::Unit {} + | ^^^^^^^^^^^^^^^^^^^^^^^ patterns `Unit`, `Tuple(_)` and `Struct { .. }` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error[E0004]: non-exhaustive patterns: `Unit`, `Tuple(_)` and `Struct { .. }` not covered + --> $DIR/enum_same_crate_empty_match.rs:35:11 + | +LL | / pub enum NormalEnum { +LL | | Unit, + | | ---- not covered +LL | | +LL | | Tuple(u32), + | | ----- not covered +LL | | +LL | | Struct { field: u32 } + | | ------ not covered +LL | | +LL | | } + | |_- `NormalEnum` defined here +... +LL | match NormalEnum::Unit {} + | ^^^^^^^^^^^^^^^^ patterns `Unit`, `Tuple(_)` and `Struct { .. }` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr index b903e9b288e..0d669a9a4e9 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr @@ -1,4 +1,4 @@ -error[E0004]: non-exhaustive patterns: pattern `IndirectUninhabitedEnum` of type `uninhabited::IndirectUninhabitedEnum` is not handled +error[E0004]: non-exhaustive patterns: type `uninhabited::IndirectUninhabitedEnum` is non-empty --> $DIR/indirect_match.rs:18:11 | LL | match x {} @@ -6,7 +6,7 @@ LL | match x {} | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms -error[E0004]: non-exhaustive patterns: pattern `IndirectUninhabitedStruct` of type `uninhabited::IndirectUninhabitedStruct` is not handled +error[E0004]: non-exhaustive patterns: type `uninhabited::IndirectUninhabitedStruct` is non-empty --> $DIR/indirect_match.rs:22:11 | LL | match x {} @@ -14,7 +14,7 @@ LL | match x {} | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms -error[E0004]: non-exhaustive patterns: pattern `IndirectUninhabitedTupleStruct` of type `uninhabited::IndirectUninhabitedTupleStruct` is not handled +error[E0004]: non-exhaustive patterns: type `uninhabited::IndirectUninhabitedTupleStruct` is non-empty --> $DIR/indirect_match.rs:26:11 | LL | match x {} @@ -22,7 +22,7 @@ LL | match x {} | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms -error[E0004]: non-exhaustive patterns: pattern `IndirectUninhabitedVariants` of type `uninhabited::IndirectUninhabitedVariants` is not handled +error[E0004]: non-exhaustive patterns: type `uninhabited::IndirectUninhabitedVariants` is non-empty --> $DIR/indirect_match.rs:32:11 | LL | match x {} diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.stderr index f94616dc64b..41a37cf6a03 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/indirect_match_same_crate.stderr @@ -1,53 +1,41 @@ -error[E0004]: non-exhaustive patterns: pattern `IndirectUninhabitedEnum` of type `IndirectUninhabitedEnum` is not handled +error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedEnum` is non-empty --> $DIR/indirect_match_same_crate.rs:32:11 | LL | pub struct IndirectUninhabitedEnum(UninhabitedEnum); - | ---------------------------------------------------- - | | | - | | variant not covered - | `IndirectUninhabitedEnum` defined here + | ---------------------------------------------------- `IndirectUninhabitedEnum` defined here ... LL | match x {} | ^ | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms -error[E0004]: non-exhaustive patterns: pattern `IndirectUninhabitedStruct` of type `IndirectUninhabitedStruct` is not handled +error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedStruct` is non-empty --> $DIR/indirect_match_same_crate.rs:36:11 | LL | pub struct IndirectUninhabitedStruct(UninhabitedStruct); - | -------------------------------------------------------- - | | | - | | variant not covered - | `IndirectUninhabitedStruct` defined here + | -------------------------------------------------------- `IndirectUninhabitedStruct` defined here ... LL | match x {} | ^ | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms -error[E0004]: non-exhaustive patterns: pattern `IndirectUninhabitedTupleStruct` of type `IndirectUninhabitedTupleStruct` is not handled +error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedTupleStruct` is non-empty --> $DIR/indirect_match_same_crate.rs:40:11 | LL | pub struct IndirectUninhabitedTupleStruct(UninhabitedTupleStruct); - | ------------------------------------------------------------------ - | | | - | | variant not covered - | `IndirectUninhabitedTupleStruct` defined here + | ------------------------------------------------------------------ `IndirectUninhabitedTupleStruct` defined here ... LL | match x {} | ^ | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms -error[E0004]: non-exhaustive patterns: pattern `IndirectUninhabitedVariants` of type `IndirectUninhabitedVariants` is not handled +error[E0004]: non-exhaustive patterns: type `IndirectUninhabitedVariants` is non-empty --> $DIR/indirect_match_same_crate.rs:46:11 | LL | pub struct IndirectUninhabitedVariants(UninhabitedVariants); - | ------------------------------------------------------------ - | | | - | | variant not covered - | `IndirectUninhabitedVariants` defined here + | ------------------------------------------------------------ `IndirectUninhabitedVariants` defined here ... LL | match x {} | ^ diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.stderr index de3fa900cd6..10a456a5a87 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match.stderr @@ -6,7 +6,7 @@ LL | match x {} | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms -error[E0004]: non-exhaustive patterns: pattern `UninhabitedStruct` of type `uninhabited::UninhabitedStruct` is not handled +error[E0004]: non-exhaustive patterns: type `uninhabited::UninhabitedStruct` is non-empty --> $DIR/match.rs:22:11 | LL | match x {} @@ -14,7 +14,7 @@ LL | match x {} | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms -error[E0004]: non-exhaustive patterns: pattern `UninhabitedTupleStruct` of type `uninhabited::UninhabitedTupleStruct` is not handled +error[E0004]: non-exhaustive patterns: type `uninhabited::UninhabitedTupleStruct` is non-empty --> $DIR/match.rs:26:11 | LL | match x {} @@ -22,11 +22,11 @@ LL | match x {} | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms -error[E0004]: non-exhaustive patterns: multiple patterns of type `uninhabited::UninhabitedVariants` are not handled +error[E0004]: non-exhaustive patterns: `Tuple(_)` and `Struct { .. }` not covered --> $DIR/match.rs:30:11 | LL | match x {} - | ^ + | ^ patterns `Tuple(_)` and `Struct { .. }` not covered | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr index 3dd1a914d55..148af8c07b1 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_same_crate.stderr @@ -1,10 +1,7 @@ -error[E0004]: non-exhaustive patterns: pattern `UninhabitedStruct` of type `UninhabitedStruct` is not handled +error[E0004]: non-exhaustive patterns: type `UninhabitedStruct` is non-empty --> $DIR/match_same_crate.rs:28:11 | -LL | pub struct UninhabitedStruct { - | - ----------------- variant not covered - | _| - | | +LL | / pub struct UninhabitedStruct { LL | | _priv: !, LL | | } | |_- `UninhabitedStruct` defined here @@ -14,33 +11,30 @@ LL | match x {} | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms -error[E0004]: non-exhaustive patterns: pattern `UninhabitedTupleStruct` of type `UninhabitedTupleStruct` is not handled +error[E0004]: non-exhaustive patterns: type `UninhabitedTupleStruct` is non-empty --> $DIR/match_same_crate.rs:32:11 | LL | pub struct UninhabitedTupleStruct(!); - | ------------------------------------- - | | | - | | variant not covered - | `UninhabitedTupleStruct` defined here + | ------------------------------------- `UninhabitedTupleStruct` defined here ... LL | match x {} | ^ | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms -error[E0004]: non-exhaustive patterns: multiple patterns of type `UninhabitedVariants` are not handled +error[E0004]: non-exhaustive patterns: `Tuple(_)` and `Struct { .. }` not covered --> $DIR/match_same_crate.rs:36:11 | LL | / pub enum UninhabitedVariants { LL | | #[non_exhaustive] Tuple(!), - | | ----- variant not covered + | | ----- not covered LL | | #[non_exhaustive] Struct { x: ! } - | | ------ variant not covered + | | ------ not covered LL | | } | |_- `UninhabitedVariants` defined here ... LL | match x {} - | ^ + | ^ patterns `Tuple(_)` and `Struct { .. }` not covered | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms diff --git a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr index 3b56c689071..2fc09c81ab0 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr @@ -22,11 +22,11 @@ LL | match x {} | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms -error[E0004]: non-exhaustive patterns: type `uninhabited::UninhabitedVariants` is non-empty +error[E0004]: non-exhaustive patterns: `Tuple(_)` and `Struct { .. }` not covered --> $DIR/match_with_exhaustive_patterns.rs:33:11 | LL | match x {} - | ^ + | ^ patterns `Tuple(_)` and `Struct { .. }` not covered | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms diff --git a/src/test/ui/span/issue-42234-unknown-receiver-type.rs b/src/test/ui/span/issue-42234-unknown-receiver-type.rs index 58138e21bc0..d3292bbecba 100644 --- a/src/test/ui/span/issue-42234-unknown-receiver-type.rs +++ b/src/test/ui/span/issue-42234-unknown-receiver-type.rs @@ -9,8 +9,8 @@ fn shines_a_beacon_through_the_darkness() { } fn courier_to_des_moines_and_points_west(data: &[u32]) -> String { - data.iter() //~ ERROR type annotations needed - .sum::<_>() + data.iter() + .sum::<_>() //~ ERROR type annotations needed .to_string() } diff --git a/src/test/ui/span/issue-42234-unknown-receiver-type.stderr b/src/test/ui/span/issue-42234-unknown-receiver-type.stderr index 30c9adb1dce..9824d879dbd 100644 --- a/src/test/ui/span/issue-42234-unknown-receiver-type.stderr +++ b/src/test/ui/span/issue-42234-unknown-receiver-type.stderr @@ -4,16 +4,15 @@ error[E0282]: type annotations needed for `std::option::Option<_>` LL | let x: Option<_> = None; | - consider giving `x` the explicit type `std::option::Option<_>`, where the type parameter `T` is specified LL | x.unwrap().method_that_could_exist_on_some_type(); - | ^^^^^^ cannot infer type for `T` + | ^^^^^^ cannot infer type for type parameter `T` | = note: type must be known at this point error[E0282]: type annotations needed - --> $DIR/issue-42234-unknown-receiver-type.rs:12:5 + --> $DIR/issue-42234-unknown-receiver-type.rs:13:10 | -LL | / data.iter() -LL | | .sum::<_>() - | |___________________^ cannot infer type +LL | .sum::<_>() + | ^^^ cannot infer type | = note: type must be known at this point diff --git a/src/test/ui/span/type-annotations-needed-expr.stderr b/src/test/ui/span/type-annotations-needed-expr.stderr index e32a542bb7a..8366285edcd 100644 --- a/src/test/ui/span/type-annotations-needed-expr.stderr +++ b/src/test/ui/span/type-annotations-needed-expr.stderr @@ -2,7 +2,10 @@ error[E0282]: type annotations needed --> $DIR/type-annotations-needed-expr.rs:2:39 | LL | let _ = (vec![1,2,3]).into_iter().sum() as f64; - | ^^^ cannot infer type for `S` + | ^^^ + | | + | cannot infer type for type parameter `S` + | help: consider specifying the type argument in the method call: `sum::<S>` | = note: type must be known at this point diff --git a/src/test/ui/traits/trait-static-method-generic-inference.stderr b/src/test/ui/traits/trait-static-method-generic-inference.stderr index 22931c5ba32..f9718dac354 100644 --- a/src/test/ui/traits/trait-static-method-generic-inference.stderr +++ b/src/test/ui/traits/trait-static-method-generic-inference.stderr @@ -1,11 +1,13 @@ -error[E0283]: type annotations needed: cannot resolve `_: base::HasNew<base::Foo>` +error[E0283]: type annotations needed --> $DIR/trait-static-method-generic-inference.rs:24:25 | LL | fn new() -> T; | -------------- required by `base::HasNew::new` ... LL | let _f: base::Foo = base::HasNew::new(); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ cannot infer type + | + = note: cannot resolve `_: base::HasNew<base::Foo>` error: aborting due to previous error diff --git a/src/test/ui/traits/traits-multidispatch-convert-ambig-dest.stderr b/src/test/ui/traits/traits-multidispatch-convert-ambig-dest.stderr index d7d27049f43..7bcda234c4b 100644 --- a/src/test/ui/traits/traits-multidispatch-convert-ambig-dest.stderr +++ b/src/test/ui/traits/traits-multidispatch-convert-ambig-dest.stderr @@ -2,7 +2,7 @@ error[E0282]: type annotations needed --> $DIR/traits-multidispatch-convert-ambig-dest.rs:26:5 | LL | test(22, std::default::Default::default()); - | ^^^^ cannot infer type for `U` + | ^^^^ cannot infer type for type parameter `U` error: aborting due to previous error diff --git a/src/test/ui/type-inference/or_else-multiple-type-params.rs b/src/test/ui/type-inference/or_else-multiple-type-params.rs new file mode 100644 index 00000000000..b15de2a4559 --- /dev/null +++ b/src/test/ui/type-inference/or_else-multiple-type-params.rs @@ -0,0 +1,10 @@ +use std::process::{Command, Stdio}; + +fn main() { + let process = Command::new("wc") + .stdout(Stdio::piped()) + .spawn() + .or_else(|err| { //~ ERROR type annotations needed + panic!("oh no: {:?}", err); + }).unwrap(); +} diff --git a/src/test/ui/type-inference/or_else-multiple-type-params.stderr b/src/test/ui/type-inference/or_else-multiple-type-params.stderr new file mode 100644 index 00000000000..141cc25ffe2 --- /dev/null +++ b/src/test/ui/type-inference/or_else-multiple-type-params.stderr @@ -0,0 +1,12 @@ +error[E0282]: type annotations needed + --> $DIR/or_else-multiple-type-params.rs:7:10 + | +LL | .or_else(|err| { + | ^^^^^^^ + | | + | cannot infer type for type parameter `F` + | help: consider specifying the type arguments in the method call: `or_else::<F, O>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/type-inference/sort_by_key.rs b/src/test/ui/type-inference/sort_by_key.rs new file mode 100644 index 00000000000..afc4d90b865 --- /dev/null +++ b/src/test/ui/type-inference/sort_by_key.rs @@ -0,0 +1,5 @@ +fn main() { + let mut lst: [([i32; 10], bool); 10] = [([0; 10], false); 10]; + lst.sort_by_key(|&(v, _)| v.iter().sum()); //~ ERROR type annotations needed + println!("{:?}", lst); +} diff --git a/src/test/ui/type-inference/sort_by_key.stderr b/src/test/ui/type-inference/sort_by_key.stderr new file mode 100644 index 00000000000..1d386bd1f42 --- /dev/null +++ b/src/test/ui/type-inference/sort_by_key.stderr @@ -0,0 +1,11 @@ +error[E0282]: type annotations needed + --> $DIR/sort_by_key.rs:3:9 + | +LL | lst.sort_by_key(|&(v, _)| v.iter().sum()); + | ^^^^^^^^^^^ --- help: consider specifying the type argument in the method call: `sum::<S>` + | | + | cannot infer type for type parameter `K` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/type-inference/unbounded-associated-type.rs b/src/test/ui/type-inference/unbounded-associated-type.rs new file mode 100644 index 00000000000..0167e943612 --- /dev/null +++ b/src/test/ui/type-inference/unbounded-associated-type.rs @@ -0,0 +1,16 @@ +trait T { + type A; + fn foo(&self) -> Self::A { + panic!() + } +} + +struct S<X>(std::marker::PhantomData<X>); + +impl<X> T for S<X> { + type A = X; +} + +fn main() { + S(std::marker::PhantomData).foo(); //~ ERROR type annotations needed +} diff --git a/src/test/ui/type-inference/unbounded-associated-type.stderr b/src/test/ui/type-inference/unbounded-associated-type.stderr new file mode 100644 index 00000000000..726dd4b4758 --- /dev/null +++ b/src/test/ui/type-inference/unbounded-associated-type.stderr @@ -0,0 +1,15 @@ +error[E0282]: type annotations needed + --> $DIR/unbounded-associated-type.rs:15:5 + | +LL | type A; + | ------- `<Self as T>::A` defined here +... +LL | S(std::marker::PhantomData).foo(); + | ^-------------------------------- + | | + | this method call resolves to `<Self as T>::A` + | cannot infer type for type parameter `X` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/type-inference/unbounded-type-param-in-fn-with-assoc-type.rs b/src/test/ui/type-inference/unbounded-type-param-in-fn-with-assoc-type.rs new file mode 100644 index 00000000000..81d054b3a1e --- /dev/null +++ b/src/test/ui/type-inference/unbounded-type-param-in-fn-with-assoc-type.rs @@ -0,0 +1,9 @@ +#[allow(invalid_type_param_default)] + +fn foo<T, U = u64>() -> (T, U) { + panic!() +} + +fn main() { + foo(); //~ ERROR type annotations needed +} diff --git a/src/test/ui/type-inference/unbounded-type-param-in-fn-with-assoc-type.stderr b/src/test/ui/type-inference/unbounded-type-param-in-fn-with-assoc-type.stderr new file mode 100644 index 00000000000..52039d0e934 --- /dev/null +++ b/src/test/ui/type-inference/unbounded-type-param-in-fn-with-assoc-type.stderr @@ -0,0 +1,9 @@ +error[E0282]: type annotations needed + --> $DIR/unbounded-type-param-in-fn-with-assoc-type.rs:8:5 + | +LL | foo(); + | ^^^ cannot infer type for type parameter `T` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/type-inference/unbounded-type-param-in-fn.rs b/src/test/ui/type-inference/unbounded-type-param-in-fn.rs new file mode 100644 index 00000000000..1f336ed59a6 --- /dev/null +++ b/src/test/ui/type-inference/unbounded-type-param-in-fn.rs @@ -0,0 +1,7 @@ +fn foo<T>() -> T { + panic!() +} + +fn main() { + foo(); //~ ERROR type annotations needed +} diff --git a/src/test/ui/type-inference/unbounded-type-param-in-fn.stderr b/src/test/ui/type-inference/unbounded-type-param-in-fn.stderr new file mode 100644 index 00000000000..8d317df6ce9 --- /dev/null +++ b/src/test/ui/type-inference/unbounded-type-param-in-fn.stderr @@ -0,0 +1,9 @@ +error[E0282]: type annotations needed + --> $DIR/unbounded-type-param-in-fn.rs:6:5 + | +LL | foo(); + | ^^^ cannot infer type for type parameter `T` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/type/type-annotation-needed.rs b/src/test/ui/type/type-annotation-needed.rs index 3b1521d5c02..a420515be49 100644 --- a/src/test/ui/type/type-annotation-needed.rs +++ b/src/test/ui/type/type-annotation-needed.rs @@ -5,4 +5,6 @@ fn foo<T: Into<String>>(x: i32) {} fn main() { foo(42); //~^ ERROR type annotations needed + //~| NOTE cannot infer type + //~| NOTE cannot resolve } diff --git a/src/test/ui/type/type-annotation-needed.stderr b/src/test/ui/type/type-annotation-needed.stderr index 460bbe9dbc4..94425440d33 100644 --- a/src/test/ui/type/type-annotation-needed.stderr +++ b/src/test/ui/type/type-annotation-needed.stderr @@ -1,4 +1,4 @@ -error[E0283]: type annotations needed: cannot resolve `_: std::convert::Into<std::string::String>` +error[E0283]: type annotations needed --> $DIR/type-annotation-needed.rs:6:5 | LL | fn foo<T: Into<String>>(x: i32) {} @@ -6,6 +6,11 @@ LL | fn foo<T: Into<String>>(x: i32) {} ... LL | foo(42); | ^^^ + | | + | cannot infer type for type parameter `T` + | help: consider specifying the type argument in the function call: `foo::<T>` + | + = note: cannot resolve `_: std::convert::Into<std::string::String>` error: aborting due to previous error diff --git a/src/test/ui/type/type-check/cannot_infer_local_or_vec.stderr b/src/test/ui/type/type-check/cannot_infer_local_or_vec.stderr index 6524bf5dd2b..53cc769bae3 100644 --- a/src/test/ui/type/type-check/cannot_infer_local_or_vec.stderr +++ b/src/test/ui/type/type-check/cannot_infer_local_or_vec.stderr @@ -2,7 +2,7 @@ error[E0282]: type annotations needed for `std::vec::Vec<T>` --> $DIR/cannot_infer_local_or_vec.rs:2:13 | LL | let x = vec![]; - | - ^^^^^^ cannot infer type for `T` + | - ^^^^^^ cannot infer type for type parameter `T` | | | consider giving `x` the explicit type `std::vec::Vec<T>`, where the type parameter `T` is specified | diff --git a/src/test/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.stderr b/src/test/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.stderr index 6d1ef240da6..df7228ce9f2 100644 --- a/src/test/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.stderr +++ b/src/test/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.stderr @@ -2,7 +2,7 @@ error[E0282]: type annotations needed for `(std::vec::Vec<T>,)` --> $DIR/cannot_infer_local_or_vec_in_tuples.rs:2:18 | LL | let (x, ) = (vec![], ); - | ----- ^^^^^^ cannot infer type for `T` + | ----- ^^^^^^ cannot infer type for type parameter `T` | | | consider giving this pattern the explicit type `(std::vec::Vec<T>,)`, where the type parameter `T` is specified | diff --git a/src/test/ui/type/type-check/issue-22897.stderr b/src/test/ui/type/type-check/issue-22897.stderr index 2b3f0696f3c..fae7b79269b 100644 --- a/src/test/ui/type/type-check/issue-22897.stderr +++ b/src/test/ui/type/type-check/issue-22897.stderr @@ -2,7 +2,7 @@ error[E0282]: type annotations needed --> $DIR/issue-22897.rs:4:5 | LL | []; - | ^^ cannot infer type for `[_; 0]` + | ^^ cannot infer type for array `[_; 0]` error: aborting due to previous error diff --git a/src/test/ui/type/type-check/issue-40294.stderr b/src/test/ui/type/type-check/issue-40294.stderr index 508783aaf2b..4fc02855091 100644 --- a/src/test/ui/type/type-check/issue-40294.stderr +++ b/src/test/ui/type/type-check/issue-40294.stderr @@ -1,4 +1,4 @@ -error[E0283]: type annotations needed: cannot resolve `&'a T: Foo` +error[E0283]: type annotations needed --> $DIR/issue-40294.rs:5:1 | LL | trait Foo: Sized { @@ -11,7 +11,9 @@ LL | | { LL | | x.foo(); LL | | y.foo(); LL | | } - | |_^ + | |_^ cannot infer type for reference `&'a T` + | + = note: cannot resolve `&'a T: Foo` error: aborting due to previous error diff --git a/src/test/ui/type/type-check/issue-67273-assignment-match-prior-arm-bool-expected-unit.rs b/src/test/ui/type/type-check/issue-67273-assignment-match-prior-arm-bool-expected-unit.rs new file mode 100644 index 00000000000..e23c0d0a40a --- /dev/null +++ b/src/test/ui/type/type-check/issue-67273-assignment-match-prior-arm-bool-expected-unit.rs @@ -0,0 +1,27 @@ +fn main() { + let mut i: i64; + // Expected type is an inference variable `?T` + // because the `match` is used as a statement. + // This is the "initial" type of the `coercion`. + match i { + // Add `bool` to the overall `coercion`. + 0 => true, + + // Necessary to cause the ICE: + 1 => true, + + // Suppose that we had `let _: bool = match i { ... }`. + // In that case, as the expected type would be `bool`, + // we would suggest `i == 1` as a fix. + // + // However, no type error happens when checking `i = 1` because `expected == ?T`, + // which will unify with `typeof(i = 1) == ()`. + // + // However, in #67273, we would delay the unification of this arm with the above + // because we used the hitherto accumulated coercion as opposed to the "initial" type. + 2 => i = 1, + //~^ ERROR match arms have incompatible types + + _ => (), + } +} diff --git a/src/test/ui/type/type-check/issue-67273-assignment-match-prior-arm-bool-expected-unit.stderr b/src/test/ui/type/type-check/issue-67273-assignment-match-prior-arm-bool-expected-unit.stderr new file mode 100644 index 00000000000..3547285542a --- /dev/null +++ b/src/test/ui/type/type-check/issue-67273-assignment-match-prior-arm-bool-expected-unit.stderr @@ -0,0 +1,22 @@ +error[E0308]: match arms have incompatible types + --> $DIR/issue-67273-assignment-match-prior-arm-bool-expected-unit.rs:22:14 + | +LL | / match i { +LL | | // Add `bool` to the overall `coercion`. +LL | | 0 => true, + | | ---- this is found to be of type `bool` +LL | | +LL | | // Necessary to cause the ICE: +LL | | 1 => true, + | | ---- this is found to be of type `bool` +... | +LL | | 2 => i = 1, + | | ^^^^^ expected `bool`, found `()` +... | +LL | | _ => (), +LL | | } + | |_____- `match` arms have incompatible types + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/unconstrained-none.stderr b/src/test/ui/unconstrained-none.stderr index eb918b25d2b..6c4fde94a61 100644 --- a/src/test/ui/unconstrained-none.stderr +++ b/src/test/ui/unconstrained-none.stderr @@ -2,7 +2,7 @@ error[E0282]: type annotations needed --> $DIR/unconstrained-none.rs:4:5 | LL | None; - | ^^^^ cannot infer type for `T` + | ^^^^ cannot infer type for type parameter `T` error: aborting due to previous error diff --git a/src/test/ui/unconstrained-ref.stderr b/src/test/ui/unconstrained-ref.stderr index d9a129a2d7b..d6985a61daf 100644 --- a/src/test/ui/unconstrained-ref.stderr +++ b/src/test/ui/unconstrained-ref.stderr @@ -2,7 +2,7 @@ error[E0282]: type annotations needed --> $DIR/unconstrained-ref.rs:6:5 | LL | S { o: &None }; - | ^ cannot infer type for `T` + | ^ cannot infer type for type parameter `T` error: aborting due to previous error diff --git a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr index 7af6075262c..18ffdccb9b2 100644 --- a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr +++ b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr @@ -9,6 +9,9 @@ LL | let _ = match x { error[E0004]: non-exhaustive patterns: type `&Void` is non-empty --> $DIR/uninhabited-matches-feature-gated.rs:12:19 | +LL | enum Void {} + | ------------ `Void` defined here +... LL | let _ = match x {}; | ^ | diff --git a/src/test/ui/vector-no-ann.stderr b/src/test/ui/vector-no-ann.stderr index 28100d7c89e..62fc42fbae4 100644 --- a/src/test/ui/vector-no-ann.stderr +++ b/src/test/ui/vector-no-ann.stderr @@ -2,7 +2,7 @@ error[E0282]: type annotations needed for `std::vec::Vec<T>` --> $DIR/vector-no-ann.rs:2:16 | LL | let _foo = Vec::new(); - | ---- ^^^^^^^^ cannot infer type for `T` + | ---- ^^^^^^^^ cannot infer type for type parameter `T` | | | consider giving `_foo` the explicit type `std::vec::Vec<T>`, where the type parameter `T` is specified diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 7b928a2e7c2..36e412975b9 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -135,6 +135,7 @@ const WHITELIST: &[Crate<'_>] = &[ Crate("polonius-engine"), Crate("ppv-lite86"), Crate("proc-macro2"), + Crate("punycode"), Crate("quick-error"), Crate("quote"), Crate("rand"), |
