diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c3a9a68963eb..37a217d2a045 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -128,6 +128,14 @@ the master branch to your feature branch. Also, please make sure that fixup commits are squashed into other related commits with meaningful commit messages. +GitHub allows [closing issues using keywords][closing-keywords]. This feature +should be used to keep the issue tracker tidy. However, it is generally preferred +to put the "closes #123" text in the PR description rather than the issue commit; +particularly during rebasing, citing the issue number in the commit can "spam" +the issue in question. + +[closing-keywords]: https://help.github.com/en/articles/closing-issues-using-keywords + Please make sure your pull request is in compliance with Rust's style guidelines by running diff --git a/Cargo.lock b/Cargo.lock index e83d38b569ff..a8fc36063fb2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -556,9 +556,9 @@ dependencies = [ [[package]] name = "compiletest_rs" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "676a74b493d50ac33cacd83fd536597e6b52c0b46b9856f7b9c809d82fef4ac0" +checksum = "f75b10a18fb53549fdd090846eb01c7f8593914494d1faabc4d3005c436e417a" dependencies = [ "diff", "filetime", @@ -1297,9 +1297,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6587d09be37fb98a11cb08b9000a3f592451c1b1b613ca69d949160e313a430a" +checksum = "3cd9867f119b19fecb08cd5c326ad4488d7a1da4bf75b4d95d71db742525aaab" dependencies = [ "autocfg", "compiler_builtins", @@ -3494,6 +3494,7 @@ dependencies = [ "rustc_data_structures", "rustc_errors", "rustc_interface", + "rustc_lint", "rustc_metadata", "rustc_mir", "rustc_plugin", @@ -4156,9 +4157,8 @@ dependencies = [ "core", "dlmalloc", "fortanix-sgx-abi", - "hashbrown 0.6.1", + "hashbrown 0.6.2", "hermit-abi", - "libc", "panic_abort", "panic_unwind", "profiler_builtins", diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index b8071b98f707..2748903f2d47 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -443,6 +443,7 @@ impl<'a> Builder<'a> { dist::Rustc, dist::DebuggerScripts, dist::Std, + dist::RustcDev, dist::Analysis, dist::Src, dist::PlainSourceTarball, diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index cadb9a7e441f..df1c72575846 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -55,6 +55,7 @@ impl Step for Std { cargo, args(builder.kind), &libstd_stamp(builder, compiler, target), + vec![], true); let libdir = builder.sysroot_libdir(compiler, target); @@ -103,6 +104,7 @@ impl Step for Rustc { cargo, args(builder.kind), &librustc_stamp(builder, compiler, target), + vec![], true); let libdir = builder.sysroot_libdir(compiler, target); @@ -155,6 +157,7 @@ impl Step for CodegenBackend { cargo, args(builder.kind), &codegen_backend_stamp(builder, compiler, target, backend), + vec![], true); } } @@ -199,6 +202,7 @@ impl Step for Rustdoc { cargo, args(builder.kind), &rustdoc_stamp(builder, compiler, target), + vec![], true); let libdir = builder.sysroot_libdir(compiler, target); diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 5074b035789a..da8d43ed49b7 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -69,7 +69,7 @@ impl Step for Std { return; } - builder.ensure(StartupObjects { compiler, target }); + let mut target_deps = builder.ensure(StartupObjects { compiler, target }); let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target); if compiler_to_use != compiler { @@ -91,7 +91,7 @@ impl Step for Std { return; } - copy_third_party_objects(builder, &compiler, target); + target_deps.extend(copy_third_party_objects(builder, &compiler, target).into_iter()); let mut cargo = builder.cargo(compiler, Mode::Std, target, "build"); std_cargo(builder, &compiler, target, &mut cargo); @@ -102,6 +102,7 @@ impl Step for Std { cargo, vec![], &libstd_stamp(builder, compiler, target), + target_deps, false); builder.ensure(StdLink { @@ -113,9 +114,22 @@ impl Step for Std { } /// Copies third pary objects needed by various targets. -fn copy_third_party_objects(builder: &Builder<'_>, compiler: &Compiler, target: Interned) { +fn copy_third_party_objects(builder: &Builder<'_>, compiler: &Compiler, target: Interned) + -> Vec +{ let libdir = builder.sysroot_libdir(*compiler, target); + let mut target_deps = vec![]; + + let mut copy_and_stamp = |sourcedir: &Path, name: &str| { + let target = libdir.join(name); + builder.copy( + &sourcedir.join(name), + &target, + ); + target_deps.push(target); + }; + // Copies the crt(1,i,n).o startup objects // // Since musl supports fully static linking, we can cross link for it even @@ -123,19 +137,13 @@ fn copy_third_party_objects(builder: &Builder<'_>, compiler: &Compiler, target: // files. As those shipped with glibc won't work, copy the ones provided by // musl so we have them on linux-gnu hosts. if target.contains("musl") { + let srcdir = builder.musl_root(target).unwrap().join("lib"); for &obj in &["crt1.o", "crti.o", "crtn.o"] { - builder.copy( - &builder.musl_root(target).unwrap().join("lib").join(obj), - &libdir.join(obj), - ); + copy_and_stamp(&srcdir, obj); } } else if target.ends_with("-wasi") { - for &obj in &["crt1.o"] { - builder.copy( - &builder.wasi_root(target).unwrap().join("lib/wasm32-wasi").join(obj), - &libdir.join(obj), - ); - } + let srcdir = builder.wasi_root(target).unwrap().join("lib/wasm32-wasi"); + copy_and_stamp(&srcdir, "crt1.o"); } // Copies libunwind.a compiled to be linked wit x86_64-fortanix-unknown-sgx. @@ -145,11 +153,11 @@ fn copy_third_party_objects(builder: &Builder<'_>, compiler: &Compiler, target: // which is provided by std for this target. if target == "x86_64-fortanix-unknown-sgx" { let src_path_env = "X86_FORTANIX_SGX_LIBS"; - let obj = "libunwind.a"; let src = env::var(src_path_env).expect(&format!("{} not found in env", src_path_env)); - let src = Path::new(&src).join(obj); - builder.copy(&src, &libdir.join(obj)); + copy_and_stamp(Path::new(&src), "libunwind.a"); } + + target_deps } /// Configure cargo to compile the standard library, adding appropriate env vars @@ -306,7 +314,7 @@ pub struct StartupObjects { } impl Step for StartupObjects { - type Output = (); + type Output = Vec; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.path("src/rtstartup") @@ -325,13 +333,15 @@ impl Step for StartupObjects { /// They don't require any library support as they're just plain old object /// files, so we just use the nightly snapshot compiler to always build them (as /// no other compilers are guaranteed to be available). - fn run(self, builder: &Builder<'_>) { + fn run(self, builder: &Builder<'_>) -> Vec { let for_compiler = self.compiler; let target = self.target; if !target.contains("windows-gnu") { - return + return vec![] } + let mut target_deps = vec![]; + let src_dir = &builder.src.join("src/rtstartup"); let dst_dir = &builder.native_dir(target).join("rtstartup"); let sysroot_dir = &builder.sysroot_libdir(for_compiler, target); @@ -350,7 +360,9 @@ impl Step for StartupObjects { .arg(src_file)); } - builder.copy(dst_file, &sysroot_dir.join(file.to_string() + ".o")); + let target = sysroot_dir.join(file.to_string() + ".o"); + builder.copy(dst_file, &target); + target_deps.push(target); } for obj in ["crt2.o", "dllcrt2.o"].iter() { @@ -358,8 +370,12 @@ impl Step for StartupObjects { builder.cc(target), target, obj); - builder.copy(&src, &sysroot_dir.join(obj)); + let target = sysroot_dir.join(obj); + builder.copy(&src, &target); + target_deps.push(target); } + + target_deps } } @@ -437,6 +453,7 @@ impl Step for Rustc { cargo, vec![], &librustc_stamp(builder, compiler, target), + vec![], false); builder.ensure(RustcLink { @@ -585,7 +602,7 @@ impl Step for CodegenBackend { let tmp_stamp = out_dir.join(".tmp.stamp"); - let files = run_cargo(builder, cargo, vec![], &tmp_stamp, false); + let files = run_cargo(builder, cargo, vec![], &tmp_stamp, vec![], false); if builder.config.dry_run { return; } @@ -941,6 +958,7 @@ pub fn run_cargo(builder: &Builder<'_>, cargo: Cargo, tail_args: Vec, stamp: &Path, + additional_target_deps: Vec, is_check: bool) -> Vec { @@ -1057,6 +1075,7 @@ pub fn run_cargo(builder: &Builder<'_>, deps.push((path_to_add.into(), false)); } + deps.extend(additional_target_deps.into_iter().map(|d| (d, false))); deps.sort(); let mut new_contents = Vec::new(); for (dep, proc_macro) in deps.iter() { diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 514ad1144491..93143570b0fe 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -637,6 +637,28 @@ impl Step for DebuggerScripts { } } +fn skip_host_target_lib(builder: &Builder<'_>, compiler: Compiler) -> bool { + // The only true set of target libraries came from the build triple, so + // let's reduce redundant work by only producing archives from that host. + if compiler.host != builder.config.build { + builder.info("\tskipping, not a build host"); + true + } else { + false + } +} + +/// Copy stamped files into an image's `target/lib` directory. +fn copy_target_libs(builder: &Builder<'_>, target: &str, image: &Path, stamp: &Path) { + let dst = image.join("lib/rustlib").join(target).join("lib"); + t!(fs::create_dir_all(&dst)); + for (path, host) in builder.read_stamp_file(stamp) { + if !host || builder.config.build == target { + builder.copy(&path, &dst.join(path.file_name().unwrap())); + } + } +} + #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] pub struct Std { pub compiler: Compiler, @@ -667,44 +689,19 @@ impl Step for Std { let target = self.target; let name = pkgname(builder, "rust-std"); - - // The only true set of target libraries came from the build triple, so - // let's reduce redundant work by only producing archives from that host. - if compiler.host != builder.config.build { - builder.info("\tskipping, not a build host"); - return distdir(builder).join(format!("{}-{}.tar.gz", name, target)); + let archive = distdir(builder).join(format!("{}-{}.tar.gz", name, target)); + if skip_host_target_lib(builder, compiler) { + return archive; } - // We want to package up as many target libraries as possible - // for the `rust-std` package, so if this is a host target we - // depend on librustc and otherwise we just depend on libtest. - if builder.hosts.iter().any(|t| t == target) { - builder.ensure(compile::Rustc { compiler, target }); - } else { - builder.ensure(compile::Std { compiler, target }); - } + builder.ensure(compile::Std { compiler, target }); let image = tmpdir(builder).join(format!("{}-{}-image", name, target)); let _ = fs::remove_dir_all(&image); - let dst = image.join("lib/rustlib").join(target); - t!(fs::create_dir_all(&dst)); - let mut src = builder.sysroot_libdir(compiler, target).to_path_buf(); - src.pop(); // Remove the trailing /lib folder from the sysroot_libdir - builder.cp_filtered(&src, &dst, &|path| { - if let Some(name) = path.file_name().and_then(|s| s.to_str()) { - if name == builder.config.rust_codegen_backends_dir.as_str() { - return false - } - if name == "bin" { - return false - } - if name.contains("LLVM") { - return false - } - } - true - }); + let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target); + let stamp = compile::libstd_stamp(builder, compiler_to_use, target); + copy_target_libs(builder, &target, &image, &stamp); let mut cmd = rust_installer(builder); cmd.arg("generate") @@ -723,7 +720,73 @@ impl Step for Std { let _time = timeit(builder); builder.run(&mut cmd); builder.remove_dir(&image); - distdir(builder).join(format!("{}-{}.tar.gz", name, target)) + archive + } +} + +#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] +pub struct RustcDev { + pub compiler: Compiler, + pub target: Interned, +} + +impl Step for RustcDev { + type Output = PathBuf; + const DEFAULT: bool = true; + const ONLY_HOSTS: bool = true; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.path("rustc-dev") + } + + fn make_run(run: RunConfig<'_>) { + run.builder.ensure(RustcDev { + compiler: run.builder.compiler_for( + run.builder.top_stage, + run.builder.config.build, + run.target, + ), + target: run.target, + }); + } + + fn run(self, builder: &Builder<'_>) -> PathBuf { + let compiler = self.compiler; + let target = self.target; + + let name = pkgname(builder, "rustc-dev"); + let archive = distdir(builder).join(format!("{}-{}.tar.gz", name, target)); + if skip_host_target_lib(builder, compiler) { + return archive; + } + + builder.ensure(compile::Rustc { compiler, target }); + + let image = tmpdir(builder).join(format!("{}-{}-image", name, target)); + let _ = fs::remove_dir_all(&image); + + let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target); + let stamp = compile::librustc_stamp(builder, compiler_to_use, target); + copy_target_libs(builder, &target, &image, &stamp); + + let mut cmd = rust_installer(builder); + cmd.arg("generate") + .arg("--product-name=Rust") + .arg("--rel-manifest-dir=rustlib") + .arg("--success-message=Rust-is-ready-to-develop.") + .arg("--image-dir").arg(&image) + .arg("--work-dir").arg(&tmpdir(builder)) + .arg("--output-dir").arg(&distdir(builder)) + .arg(format!("--package-name={}-{}", name, target)) + .arg(format!("--component-name=rustc-dev-{}", target)) + .arg("--legacy-manifest-dirs=rustlib,cargo"); + + builder.info(&format!("Dist rustc-dev stage{} ({} -> {})", + compiler.stage, &compiler.host, target)); + let _time = timeit(builder); + builder.run(&mut cmd); + builder.remove_dir(&image); + archive } } diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 42c3cfbd84ab..cbdb174c02d9 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -1137,6 +1137,7 @@ impl Build { pub fn copy(&self, src: &Path, dst: &Path) { if self.config.dry_run { return; } self.verbose_than(1, &format!("Copy {:?} to {:?}", src, dst)); + if src == dst { return; } let _ = fs::remove_file(&dst); let metadata = t!(src.symlink_metadata()); if metadata.file_type().is_symlink() { diff --git a/src/ci/azure-pipelines/steps/install-windows-build-deps.yml b/src/ci/azure-pipelines/steps/install-windows-build-deps.yml index bd4f1ed0cea4..812339900fe4 100644 --- a/src/ci/azure-pipelines/steps/install-windows-build-deps.yml +++ b/src/ci/azure-pipelines/steps/install-windows-build-deps.yml @@ -84,6 +84,17 @@ steps: condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT'), ne(variables['MINGW_URL'],'')) displayName: Download custom MinGW +# FIXME(#65767): workaround msys bug, step 1 +- bash: | + set -e + arch=i686 + if [ "$MSYS_BITS" = "64" ]; then + arch=x86_64 + fi + curl -O https://ci-mirrors.rust-lang.org/rustc/msys2-repo/mingw/$arch/mingw-w64-$arch-ca-certificates-20180409-1-any.pkg.tar.xz + condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) + displayName: Download working ca-certificates for msys + # Otherwise install MinGW through `pacman` - bash: | set -e @@ -96,6 +107,18 @@ steps: condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT'), eq(variables['MINGW_URL'],'')) displayName: Download standard MinGW +# FIXME(#65767): workaround msys bug, step 2 +- bash: | + set -e + arch=i686 + if [ "$MSYS_BITS" = "64" ]; then + arch=x86_64 + fi + pacman -U --noconfirm --noprogressbar mingw-w64-$arch-ca-certificates-20180409-1-any.pkg.tar.xz + rm mingw-w64-$arch-ca-certificates-20180409-1-any.pkg.tar.xz + condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) + displayName: Install working ca-certificates for msys + # Make sure we use the native python interpreter instead of some msys equivalent # one way or another. The msys interpreters seem to have weird path conversions # baked in which break LLVM's build system one way or another, so let's use the diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index d5564fd798f3..b603c7b231e6 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -14,6 +14,7 @@ - [Targets](targets/index.md) - [Built-in Targets](targets/built-in.md) - [Custom Targets](targets/custom.md) + - [Known Issues](targets/known-issues.md) - [Profile-guided Optimization](profile-guided-optimization.md) - [Linker-plugin based LTO](linker-plugin-lto.md) - [Contributing to `rustc`](contributing.md) diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index e73fd43f19a5..f5d5f2089d7e 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -61,6 +61,8 @@ enabling or disabling a feature. To see the valid options and an example of use, run `rustc --print target-features`. +Using this flag is unsafe and might result in [undefined runtime behavior](../targets/known-issues.md). + ## passes This flag can be used to add extra LLVM passes to the compilation. diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md index b2cc65c11fd2..bdb3c5196585 100644 --- a/src/doc/rustc/src/command-line-arguments.md +++ b/src/doc/rustc/src/command-line-arguments.md @@ -145,7 +145,7 @@ of print values are: target CPU may be selected with the `-C target-cpu=val` flag. - `target-features` — List of available target features for the current target. Target features may be enabled with the `-C target-feature=val` - flag. + flag. This flag is unsafe. See [known issues](targets/known-issues.md) for more details. - `relocation-models` — List of relocation models. Relocation models may be selected with the `-C relocation-model=val` flag. - `code-models` — List of code models. Code models may be selected with the diff --git a/src/doc/rustc/src/targets/index.md b/src/doc/rustc/src/targets/index.md index 3d63d072befe..5859df83f645 100644 --- a/src/doc/rustc/src/targets/index.md +++ b/src/doc/rustc/src/targets/index.md @@ -11,3 +11,9 @@ To compile to a particular target, use the `--target` flag: ```bash $ rustc src/main.rs --target=wasm32-unknown-unknown ``` +## Target Features +`x86`, and `ARMv8` are two popular CPU architectures. Their instruction sets form a common baseline across most CPUs. However, some CPUs extend these with custom instruction sets, e.g. vector (`AVX`), bitwise manipulation (`BMI`) or cryptographic (`AES`). + +Developers, who know on which CPUs their compiled code is going to run can choose to add (or remove) CPU specific instruction sets via the `-C target-feature=val` flag. + +Please note, that this flag is generally considered as unsafe. More details can be found in [this section](known-issues.md). diff --git a/src/doc/rustc/src/targets/known-issues.md b/src/doc/rustc/src/targets/known-issues.md new file mode 100644 index 000000000000..89fd8ea6d32e --- /dev/null +++ b/src/doc/rustc/src/targets/known-issues.md @@ -0,0 +1,13 @@ +# Known Issues +This section informs you about known "gotchas". Keep in mind, that this section is (and always will be) incomplete. For suggestions and amendments, feel free to [contribute](../contributing.md) to this guide. + +## Target Features +Most target-feature problems arise, when mixing code that have the target-feature _enabled_ with code that have it _disabled_. If you want to avoid undefined behavior, it is recommended to build _all code_ (including the standard library and imported crates) with a common set of target-features. + +By default, compiling your code with the `-C target-feature` flag will not recompile the entire standard library and/or imported crates with matching target features. Therefore, target features are generally considered as unsafe. Using `#[target_feature]` on individual functions makes the function unsafe. + +Examples: + +| Target-Feature | Issue | Seen on | Description | Details | +| -------------- | ----- | ------- | ----------- | ------- | +| `+soft-float`
and
`-sse` | Segfaults and ABI mismatches | `x86` and `x86-64` | The `x86` and `x86_64` architecture uses SSE registers (aka `xmm`) for floating point operations. Using software emulated floats ("soft-floats") disables usage of `xmm` registers, but parts of Rust's core libraries (e.g. `std::f32` or `std::f64`) are compiled without soft-floats and expect parameters to be passed in `xmm` registers. This leads to ABI mismatches.

Attempting to compile with disabled SSE causes the same error, too. | [#63466](https://github.com/rust-lang/rust/issues/63466) | diff --git a/src/liballoc/borrow.rs b/src/liballoc/borrow.rs index a9c5bce4c25f..d2bdda83fa99 100644 --- a/src/liballoc/borrow.rs +++ b/src/liballoc/borrow.rs @@ -207,6 +207,47 @@ impl Clone for Cow<'_, B> { } impl Cow<'_, B> { + /// Returns true if the data is borrowed, i.e. if `to_mut` would require additional work. + /// + /// # Examples + /// + /// ``` + /// #![feature(cow_is_borrowed)] + /// use std::borrow::Cow; + /// + /// let cow = Cow::Borrowed("moo"); + /// assert!(cow.is_borrowed()); + /// + /// let bull: Cow<'_, str> = Cow::Owned("...moo?".to_string()); + /// assert!(!bull.is_borrowed()); + /// ``` + #[unstable(feature = "cow_is_borrowed", issue = "65143")] + pub fn is_borrowed(&self) -> bool { + match *self { + Borrowed(_) => true, + Owned(_) => false, + } + } + + /// Returns true if the data is owned, i.e. if `to_mut` would be a no-op. + /// + /// # Examples + /// + /// ``` + /// #![feature(cow_is_borrowed)] + /// use std::borrow::Cow; + /// + /// let cow: Cow<'_, str> = Cow::Owned("moo".to_string()); + /// assert!(cow.is_owned()); + /// + /// let bull = Cow::Borrowed("...moo?"); + /// assert!(!bull.is_owned()); + /// ``` + #[unstable(feature = "cow_is_borrowed", issue = "65143")] + pub fn is_owned(&self) -> bool { + !self.is_borrowed() + } + /// Acquires a mutable reference to the owned form of the data. /// /// Clones the data if it is not already owned. diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index 0bf573f5e253..8f3dfabd8886 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -1817,7 +1817,7 @@ impl VecDeque { } } - return elem; + elem } /// Splits the `VecDeque` into two at the given index. diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 3684162d8b18..94379afc2bd4 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -85,6 +85,7 @@ #![feature(const_generic_impls_guard)] #![feature(const_generics)] #![feature(const_in_array_repeat_expressions)] +#![feature(cow_is_borrowed)] #![feature(dispatch_from_dyn)] #![feature(core_intrinsics)] #![feature(container_error_extra)] diff --git a/src/liballoc/str.rs b/src/liballoc/str.rs index 9231c2d3f1d5..83816d8b954c 100644 --- a/src/liballoc/str.rs +++ b/src/liballoc/str.rs @@ -456,7 +456,7 @@ impl str { } } } - return s; + s } /// Converts a [`Box`] into a [`String`] without copying or allocating. diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 69f8f71197c1..80d6c6e0d439 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -1638,7 +1638,7 @@ impl Clone for Weak { } } - return Weak { ptr: self.ptr }; + Weak { ptr: self.ptr } } } diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 8413b2e0ac49..0e83a282b18f 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -2025,7 +2025,7 @@ impl Pointer for *const T { if f.alternate() { f.flags |= 1 << (FlagV1::SignAwareZeroPad as u32); - if let None = f.width { + if f.width.is_none() { f.width = Some(((mem::size_of::() * 8) / 4) + 2); } } diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index 1320e63df063..35558e3abcdd 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -238,6 +238,33 @@ macro_rules! debug_assert_ne { ($($arg:tt)*) => (if $crate::cfg!(debug_assertions) { $crate::assert_ne!($($arg)*); }) } +/// Returns whether the given expression matches any of the given patterns. +/// +/// Like in a `match` expression, the pattern can be optionally followed by `if` +/// and a guard expression that has access to names bound by the pattern. +/// +/// # Examples +/// +/// ``` +/// #![feature(matches_macro)] +/// +/// let foo = 'f'; +/// assert!(matches!(foo, 'A'..='Z' | 'a'..='z')); +/// +/// let bar = Some(4); +/// assert!(matches!(bar, Some(x) if x > 2)); +/// ``` +#[macro_export] +#[unstable(feature = "matches_macro", issue = "65721")] +macro_rules! matches { + ($expression:expr, $( $pattern:pat )|+ $( if $guard: expr )?) => { + match $expression { + $( $pattern )|+ $( if $guard )? => true, + _ => false + } + } +} + /// Unwraps a result or propagates its error. /// /// The `?` operator was added to replace `try!` and should be used instead. diff --git a/src/libcore/num/dec2flt/algorithm.rs b/src/libcore/num/dec2flt/algorithm.rs index fa3c8075378c..ed89852dc48d 100644 --- a/src/libcore/num/dec2flt/algorithm.rs +++ b/src/libcore/num/dec2flt/algorithm.rs @@ -143,13 +143,12 @@ pub fn fast_path(integral: &[u8], fractional: &[u8], e: i64) -> Opt /// > not a bound for the true error, but bounds the difference between the approximation z and /// > the best possible approximation that uses p bits of significand.) pub fn bellerophon(f: &Big, e: i16) -> T { - let slop; - if f <= &Big::from_u64(T::MAX_SIG) { + let slop = if f <= &Big::from_u64(T::MAX_SIG) { // The cases abs(e) < log5(2^N) are in fast_path() - slop = if e >= 0 { 0 } else { 3 }; + if e >= 0 { 0 } else { 3 } } else { - slop = if e >= 0 { 1 } else { 4 }; - } + if e >= 0 { 1 } else { 4 } + }; let z = rawfp::big_to_fp(f).mul(&power_of_ten(e)).normalize(); let exp_p_n = 1 << (P - T::SIG_BITS as u32); let lowbits: i64 = (z.f % exp_p_n) as i64; diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 9eb29eae7f75..89f2d7ab29c9 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -837,9 +837,8 @@ impl Option { #[inline] #[stable(feature = "option_entry", since = "1.20.0")] pub fn get_or_insert_with T>(&mut self, f: F) -> &mut T { - match *self { - None => *self = Some(f()), - _ => (), + if let None = *self { + *self = Some(f()); } match *self { diff --git a/src/libpanic_unwind/gcc.rs b/src/libpanic_unwind/gcc.rs index 236ed1505057..a35847c85fc2 100644 --- a/src/libpanic_unwind/gcc.rs +++ b/src/libpanic_unwind/gcc.rs @@ -156,21 +156,21 @@ unsafe extern "C" fn rust_eh_personality(version: c_int, if actions as i32 & uw::_UA_SEARCH_PHASE as i32 != 0 { match eh_action { EHAction::None | - EHAction::Cleanup(_) => return uw::_URC_CONTINUE_UNWIND, - EHAction::Catch(_) => return uw::_URC_HANDLER_FOUND, - EHAction::Terminate => return uw::_URC_FATAL_PHASE1_ERROR, + EHAction::Cleanup(_) => uw::_URC_CONTINUE_UNWIND, + EHAction::Catch(_) => uw::_URC_HANDLER_FOUND, + EHAction::Terminate => uw::_URC_FATAL_PHASE1_ERROR, } } else { match eh_action { - EHAction::None => return uw::_URC_CONTINUE_UNWIND, + EHAction::None => uw::_URC_CONTINUE_UNWIND, EHAction::Cleanup(lpad) | EHAction::Catch(lpad) => { uw::_Unwind_SetGR(context, UNWIND_DATA_REG.0, exception_object as uintptr_t); uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, 0); uw::_Unwind_SetIP(context, lpad); - return uw::_URC_INSTALL_CONTEXT; + uw::_URC_INSTALL_CONTEXT } - EHAction::Terminate => return uw::_URC_FATAL_PHASE2_ERROR, + EHAction::Terminate => uw::_URC_FATAL_PHASE2_ERROR, } } } diff --git a/src/libpanic_unwind/seh64_gnu.rs b/src/libpanic_unwind/seh64_gnu.rs index 457ffcd34f9c..16b699a44379 100644 --- a/src/libpanic_unwind/seh64_gnu.rs +++ b/src/libpanic_unwind/seh64_gnu.rs @@ -46,7 +46,7 @@ pub fn payload() -> *mut u8 { pub unsafe fn cleanup(ptr: *mut u8) -> Box { let panic_ctx = Box::from_raw(ptr as *mut PanicData); - return panic_ctx.data; + panic_ctx.data } // SEH doesn't support resuming unwinds after calling a landing pad like diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 0686bec0621f..dea8d70aaf4e 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -59,7 +59,7 @@ use crate::ich::{Fingerprint, StableHashingContext}; use rustc_data_structures::stable_hasher::{StableHasher, HashStable}; use std::fmt; use std::hash::Hash; -use syntax_pos::symbol::InternedString; +use syntax_pos::symbol::Symbol; use crate::traits; use crate::traits::query::{ CanonicalProjectionGoal, CanonicalTyGoal, CanonicalTypeOpAscribeUserTypeGoal, @@ -426,7 +426,7 @@ rustc_dep_node_append!([define_dep_nodes!][ <'tcx> [anon] TraitSelect, - [] CompileCodegenUnit(InternedString), + [] CompileCodegenUnit(Symbol), [eval_always] Analysis(CrateNum), ]); diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs index 3d501cacf6f4..122ae4a6cf66 100644 --- a/src/librustc/error_codes.rs +++ b/src/librustc/error_codes.rs @@ -2045,8 +2045,8 @@ so that a generator can then be constructed: async fn bar() -> () {} async fn foo() { - bar::().await; - // ^^^^^^^^ specify type explicitly + bar::().await; + // ^^^^^^^^ specify type explicitly } ``` "##, @@ -2126,6 +2126,84 @@ static X: u32 = 42; ``` "##, +E0728: r##" +[`await`] has been used outside [`async`] function or block. + +Erroneous code examples: + +```edition2018,compile_fail,E0728 +# use std::pin::Pin; +# use std::future::Future; +# use std::task::{Context, Poll}; +# +# struct WakeOnceThenComplete(bool); +# +# fn wake_and_yield_once() -> WakeOnceThenComplete { +# WakeOnceThenComplete(false) +# } +# +# impl Future for WakeOnceThenComplete { +# type Output = (); +# fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { +# if self.0 { +# Poll::Ready(()) +# } else { +# cx.waker().wake_by_ref(); +# self.0 = true; +# Poll::Pending +# } +# } +# } +# +fn foo() { + wake_and_yield_once().await // `await` is used outside `async` context +} +``` + +[`await`] is used to suspend the current computation until the given +future is ready to produce a value. So it is legal only within +an [`async`] context, like an `async fn` or an `async` block. + +```edition2018 +# use std::pin::Pin; +# use std::future::Future; +# use std::task::{Context, Poll}; +# +# struct WakeOnceThenComplete(bool); +# +# fn wake_and_yield_once() -> WakeOnceThenComplete { +# WakeOnceThenComplete(false) +# } +# +# impl Future for WakeOnceThenComplete { +# type Output = (); +# fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { +# if self.0 { +# Poll::Ready(()) +# } else { +# cx.waker().wake_by_ref(); +# self.0 = true; +# Poll::Pending +# } +# } +# } +# +async fn foo() { + wake_and_yield_once().await // `await` is used within `async` function +} + +fn bar(x: u8) -> impl Future { + async move { + wake_and_yield_once().await; // `await` is used within `async` block + x + } +} +``` + +[`async`]: https://doc.rust-lang.org/std/keyword.async.html +[`await`]: https://doc.rust-lang.org/std/keyword.await.html +"##, + E0734: r##" A stability attribute has been used outside of the standard library. @@ -2218,6 +2296,5 @@ See [RFC 2091] for details on this and other limitations. // E0702, // replaced with a generic attribute input check E0726, // non-explicit (not `'_`) elided lifetime in unsupported position E0727, // `async` generators are not yet supported - E0728, // `await` must be in an `async` function or block E0739, // invalid track_caller application/syntax } diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index d5287fd415b7..002e6874466b 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -83,8 +83,6 @@ pub struct LoweringContext<'a> { /// Used to assign IDs to HIR nodes that do not directly correspond to AST nodes. sess: &'a Session, - cstore: &'a dyn CrateStore, - resolver: &'a mut dyn Resolver, /// HACK(Centril): there is a cyclic dependency between the parser and lowering @@ -160,6 +158,8 @@ pub struct LoweringContext<'a> { } pub trait Resolver { + fn cstore(&self) -> &dyn CrateStore; + /// Obtains resolution for a `NodeId` with a single resolution. fn get_partial_res(&mut self, id: NodeId) -> Option; @@ -240,7 +240,6 @@ impl<'a> ImplTraitContext<'a> { pub fn lower_crate( sess: &Session, - cstore: &dyn CrateStore, dep_graph: &DepGraph, krate: &Crate, resolver: &mut dyn Resolver, @@ -256,7 +255,6 @@ pub fn lower_crate( LoweringContext { crate_root: sess.parse_sess.injected_crate_name.try_get().copied(), sess, - cstore, resolver, nt_to_tokenstream, items: BTreeMap::new(), @@ -792,15 +790,15 @@ impl<'a> LoweringContext<'a> { // really show up for end-user. let (str_name, kind) = match hir_name { ParamName::Plain(ident) => ( - ident.as_interned_str(), + ident.name, hir::LifetimeParamKind::InBand, ), ParamName::Fresh(_) => ( - kw::UnderscoreLifetime.as_interned_str(), + kw::UnderscoreLifetime, hir::LifetimeParamKind::Elided, ), ParamName::Error => ( - kw::UnderscoreLifetime.as_interned_str(), + kw::UnderscoreLifetime, hir::LifetimeParamKind::Error, ), }; @@ -980,7 +978,7 @@ impl<'a> LoweringContext<'a> { if id.is_local() { self.resolver.definitions().def_key(id.index) } else { - self.cstore.def_key(id) + self.resolver.cstore().def_key(id) } } @@ -1590,7 +1588,7 @@ impl<'a> LoweringContext<'a> { self.context.resolver.definitions().create_def_with_parent( self.parent, def_node_id, - DefPathData::LifetimeNs(name.ident().as_interned_str()), + DefPathData::LifetimeNs(name.ident().name), ExpnId::root(), lifetime.span); @@ -1727,8 +1725,8 @@ impl<'a> LoweringContext<'a> { return n; } assert!(!def_id.is_local()); - let item_generics = - self.cstore.item_generics_cloned_untracked(def_id, self.sess); + let item_generics = self.resolver.cstore() + .item_generics_cloned_untracked(def_id, self.sess); let n = item_generics.own_counts().lifetimes; self.type_def_lifetime_params.insert(def_id, n); n diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index 1a970c7a2c1e..307dbe7dab08 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -186,13 +186,13 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { }); let mut upstream_crates: Vec<_> = cstore.crates_untracked().iter().map(|&cnum| { - let name = cstore.crate_name_untracked(cnum).as_interned_str(); + let name = cstore.crate_name_untracked(cnum); let disambiguator = cstore.crate_disambiguator_untracked(cnum).to_fingerprint(); let hash = cstore.crate_hash_untracked(cnum); (name, disambiguator, hash) }).collect(); - upstream_crates.sort_unstable_by_key(|&(name, dis, _)| (name, dis)); + upstream_crates.sort_unstable_by_key(|&(name, dis, _)| (name.as_str(), dis)); // We hash the final, remapped names of all local source files so we // don't have to include the path prefix remapping commandline args. diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index 9be339be7034..7c8fdcc8b12e 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -57,7 +57,7 @@ impl<'a> DefCollector<'a> { // For async functions, we need to create their inner defs inside of a // closure to match their desugared representation. - let fn_def_data = DefPathData::ValueNs(name.as_interned_str()); + let fn_def_data = DefPathData::ValueNs(name); let fn_def = self.create_def(id, fn_def_data, span); return self.with_parent(fn_def, |this| { this.create_def(return_impl_trait_id, DefPathData::ImplTrait, span); @@ -83,8 +83,7 @@ impl<'a> DefCollector<'a> { .unwrap_or_else(|| { let node_id = NodeId::placeholder_from_expn_id(self.expansion); sym::integer(self.definitions.placeholder_field_indices[&node_id]) - }) - .as_interned_str(); + }); let def = self.create_def(field.id, DefPathData::ValueNs(name), field.span); self.with_parent(def, |this| visit::walk_struct_field(this, field)); } @@ -109,7 +108,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { ItemKind::Mod(..) | ItemKind::Trait(..) | ItemKind::TraitAlias(..) | ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) | ItemKind::OpaqueTy(..) | ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | - ItemKind::TyAlias(..) => DefPathData::TypeNs(i.ident.as_interned_str()), + ItemKind::TyAlias(..) => DefPathData::TypeNs(i.ident.name), ItemKind::Fn( ref decl, ref header, @@ -127,8 +126,8 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { ) } ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) => - DefPathData::ValueNs(i.ident.as_interned_str()), - ItemKind::MacroDef(..) => DefPathData::MacroNs(i.ident.as_interned_str()), + DefPathData::ValueNs(i.ident.name), + ItemKind::MacroDef(..) => DefPathData::MacroNs(i.ident.name), ItemKind::Mac(..) => return self.visit_macro_invoc(i.id), ItemKind::GlobalAsm(..) => DefPathData::Misc, ItemKind::Use(..) => { @@ -162,7 +161,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { } let def = self.create_def(foreign_item.id, - DefPathData::ValueNs(foreign_item.ident.as_interned_str()), + DefPathData::ValueNs(foreign_item.ident.name), foreign_item.span); self.with_parent(def, |this| { @@ -175,7 +174,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { return self.visit_macro_invoc(v.id); } let def = self.create_def(v.id, - DefPathData::TypeNs(v.ident.as_interned_str()), + DefPathData::TypeNs(v.ident.name), v.span); self.with_parent(def, |this| { if let Some(ctor_hir_id) = v.data.ctor_id() { @@ -202,7 +201,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { self.visit_macro_invoc(param.id); return; } - let name = param.ident.as_interned_str(); + let name = param.ident.name; let def_path_data = match param.kind { GenericParamKind::Lifetime { .. } => DefPathData::LifetimeNs(name), GenericParamKind::Type { .. } => DefPathData::TypeNs(name), @@ -216,9 +215,9 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { fn visit_trait_item(&mut self, ti: &'a TraitItem) { let def_data = match ti.kind { TraitItemKind::Method(..) | TraitItemKind::Const(..) => - DefPathData::ValueNs(ti.ident.as_interned_str()), + DefPathData::ValueNs(ti.ident.name), TraitItemKind::Type(..) => { - DefPathData::TypeNs(ti.ident.as_interned_str()) + DefPathData::TypeNs(ti.ident.name) }, TraitItemKind::Macro(..) => return self.visit_macro_invoc(ti.id), }; @@ -243,12 +242,10 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { body, ) } - ImplItemKind::Method(..) | ImplItemKind::Const(..) => - DefPathData::ValueNs(ii.ident.as_interned_str()), + ImplItemKind::Method(..) | + ImplItemKind::Const(..) => DefPathData::ValueNs(ii.ident.name), ImplItemKind::TyAlias(..) | - ImplItemKind::OpaqueTy(..) => { - DefPathData::TypeNs(ii.ident.as_interned_str()) - }, + ImplItemKind::OpaqueTy(..) => DefPathData::TypeNs(ii.ident.name), ImplItemKind::Macro(..) => return self.visit_macro_invoc(ii.id), }; diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index d95637c3b986..5993a97c40d6 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -18,7 +18,7 @@ use std::fmt::Write; use std::hash::Hash; use syntax::ast; use syntax_expand::hygiene::ExpnId; -use syntax::symbol::{Symbol, sym, InternedString}; +use syntax::symbol::{Symbol, sym}; use syntax_pos::{Span, DUMMY_SP}; /// The `DefPathTable` maps `DefIndex`es to `DefKey`s and vice versa. @@ -136,7 +136,9 @@ impl DefKey { ::std::mem::discriminant(data).hash(&mut hasher); if let Some(name) = data.get_opt_name() { - name.hash(&mut hasher); + // Get a stable hash by considering the symbol chars rather than + // the symbol index. + name.as_str().hash(&mut hasher); } disambiguator.hash(&mut hasher); @@ -218,7 +220,7 @@ impl DefPath { for component in &self.data { write!(s, "::{}[{}]", - component.data.as_interned_str(), + component.data.as_symbol(), component.disambiguator) .unwrap(); } @@ -238,11 +240,11 @@ impl DefPath { for component in &self.data { if component.disambiguator == 0 { - write!(s, "::{}", component.data.as_interned_str()).unwrap(); + write!(s, "::{}", component.data.as_symbol()).unwrap(); } else { write!(s, "{}[{}]", - component.data.as_interned_str(), + component.data.as_symbol(), component.disambiguator) .unwrap(); } @@ -262,11 +264,11 @@ impl DefPath { opt_delimiter.map(|d| s.push(d)); opt_delimiter = Some('-'); if component.disambiguator == 0 { - write!(s, "{}", component.data.as_interned_str()).unwrap(); + write!(s, "{}", component.data.as_symbol()).unwrap(); } else { write!(s, "{}[{}]", - component.data.as_interned_str(), + component.data.as_symbol(), component.disambiguator) .unwrap(); } @@ -290,13 +292,13 @@ pub enum DefPathData { /// An impl. Impl, /// Something in the type namespace. - TypeNs(InternedString), + TypeNs(Symbol), /// Something in the value namespace. - ValueNs(InternedString), + ValueNs(Symbol), /// Something in the macro namespace. - MacroNs(InternedString), + MacroNs(Symbol), /// Something in the lifetime namespace. - LifetimeNs(InternedString), + LifetimeNs(Symbol), /// A closure expression. ClosureExpr, @@ -311,7 +313,7 @@ pub enum DefPathData { /// Identifies a piece of crate metadata that is global to a whole crate /// (as opposed to just one item). `GlobalMetaData` components are only /// supposed to show up right below the crate root. - GlobalMetaData(InternedString), + GlobalMetaData(Symbol), } #[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug, @@ -545,7 +547,7 @@ impl Definitions { } impl DefPathData { - pub fn get_opt_name(&self) -> Option { + pub fn get_opt_name(&self) -> Option { use self::DefPathData::*; match *self { TypeNs(name) | @@ -564,15 +566,15 @@ impl DefPathData { } } - pub fn as_interned_str(&self) -> InternedString { + pub fn as_symbol(&self) -> Symbol { use self::DefPathData::*; - let s = match *self { + match *self { TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) | GlobalMetaData(name) => { - return name + name } // Note that this does not show up in user print-outs. CrateRoot => sym::double_braced_crate, @@ -582,13 +584,11 @@ impl DefPathData { Ctor => sym::double_braced_constructor, AnonConst => sym::double_braced_constant, ImplTrait => sym::double_braced_opaque, - }; - - s.as_interned_str() + } } pub fn to_string(&self) -> String { - self.as_interned_str().to_string() + self.as_symbol().to_string() } } @@ -610,7 +610,7 @@ macro_rules! define_global_metadata_kind { definitions.create_def_with_parent( CRATE_DEF_INDEX, ast::DUMMY_NODE_ID, - DefPathData::GlobalMetaData(instance.name().as_interned_str()), + DefPathData::GlobalMetaData(instance.name()), ExpnId::root(), DUMMY_SP ); @@ -624,7 +624,7 @@ macro_rules! define_global_metadata_kind { let def_key = DefKey { parent: Some(CRATE_DEF_INDEX), disambiguated_data: DisambiguatedDefPathData { - data: DefPathData::GlobalMetaData(self.name().as_interned_str()), + data: DefPathData::GlobalMetaData(self.name()), disambiguator: 0, } }; diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 364a8ace1aac..38c84ad33478 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -19,7 +19,7 @@ use crate::ty::query::Providers; use crate::util::nodemap::{NodeMap, FxHashSet}; use errors::FatalError; -use syntax_pos::{Span, DUMMY_SP, symbol::InternedString, MultiSpan}; +use syntax_pos::{Span, DUMMY_SP, MultiSpan}; use syntax::source_map::Spanned; use syntax::ast::{self, CrateSugar, Ident, Name, NodeId, AsmDialect}; use syntax::ast::{Attribute, Label, LitKind, StrStyle, FloatTy, IntTy, UintTy}; @@ -628,9 +628,9 @@ impl Generics { own_counts } - pub fn get_named(&self, name: InternedString) -> Option<&GenericParam> { + pub fn get_named(&self, name: Symbol) -> Option<&GenericParam> { for param in &self.params { - if name == param.name.ident().as_interned_str() { + if name == param.name.ident().name { return Some(param); } } diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index defc3fb25bc5..dc1f6fd3131b 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -9,7 +9,7 @@ use std::mem; use syntax::ast; use syntax::feature_gate; use syntax::parse::token; -use syntax::symbol::InternedString; +use syntax::symbol::LocalInternedString; use syntax::tokenstream; use syntax_pos::SourceFile; @@ -18,20 +18,21 @@ use crate::hir::def_id::{DefId, CrateNum, CRATE_DEF_INDEX}; use smallvec::SmallVec; use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey, StableHasher}; -impl<'a> HashStable> for InternedString { +impl<'a> HashStable> for LocalInternedString { #[inline] fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - self.with(|s| s.hash_stable(hcx, hasher)) + let str = self as &str; + str.hash_stable(hcx, hasher) } } -impl<'a> ToStableHashKey> for InternedString { - type KeyType = InternedString; +impl<'a> ToStableHashKey> for LocalInternedString { + type KeyType = LocalInternedString; #[inline] fn to_stable_hash_key(&self, _: &StableHashingContext<'a>) - -> InternedString { + -> LocalInternedString { self.clone() } } @@ -44,13 +45,13 @@ impl<'a> HashStable> for ast::Name { } impl<'a> ToStableHashKey> for ast::Name { - type KeyType = InternedString; + type KeyType = LocalInternedString; #[inline] fn to_stable_hash_key(&self, _: &StableHashingContext<'a>) - -> InternedString { - self.as_interned_str() + -> LocalInternedString { + self.as_str() } } diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs index f06dbc72cd96..51ae4e49493f 100644 --- a/src/librustc/infer/combine.rs +++ b/src/librustc/infer/combine.rs @@ -494,7 +494,7 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> { if sub_vid == self.for_vid_sub_root { // If sub-roots are equal, then `for_vid` and // `vid` are related via subtyping. - return Err(TypeError::CyclicTy(self.root_ty)); + Err(TypeError::CyclicTy(self.root_ty)) } else { match variables.probe(vid) { TypeVariableValue::Known { value: u } => { @@ -527,7 +527,7 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> { let u = self.tcx().mk_ty_var(new_var_id); debug!("generalize: replacing original vid={:?} with new={:?}", vid, u); - return Ok(u); + Ok(u) } } } @@ -602,19 +602,26 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> { ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> { assert_eq!(c, c2); // we are abusing TypeRelation here; both LHS and RHS ought to be == - match c { - ty::Const { val: ConstValue::Infer(InferConst::Var(vid)), .. } => { + match c.val { + ConstValue::Infer(InferConst::Var(vid)) => { let mut variable_table = self.infcx.const_unification_table.borrow_mut(); - match variable_table.probe_value(*vid).val.known() { - Some(u) => { - self.relate(&u, &u) + let var_value = variable_table.probe_value(vid); + match var_value.val { + ConstVariableValue::Known { value: u } => self.relate(&u, &u), + ConstVariableValue::Unknown { universe } => { + if self.for_universe.can_name(universe) { + Ok(c) + } else { + let new_var_id = variable_table.new_key(ConstVarValue { + origin: var_value.origin, + val: ConstVariableValue::Unknown { universe: self.for_universe }, + }); + Ok(self.tcx().mk_const_var(new_var_id, c.ty)) + } } - None => Ok(c), } } - _ => { - relate::super_relate_consts(self, c, c) - } + _ => relate::super_relate_consts(self, c, c), } } } diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index f6068855e630..a50cc86862e5 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -542,7 +542,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { disambiguated_data: &DisambiguatedDefPathData, ) -> Result { let mut path = print_prefix(self)?; - path.push(disambiguated_data.data.as_interned_str().to_string()); + path.push(disambiguated_data.data.as_symbol().to_string()); Ok(path) } fn path_generic_args( @@ -1146,10 +1146,17 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let span = cause.span(self.tcx); - diag.span_label(span, terr.to_string()); - if let Some((sp, msg)) = secondary_span { - diag.span_label(sp, msg); - } + // Ignore msg for object safe coercion + // since E0038 message will be printed + match terr { + TypeError::ObjectUnsafeCoercion(_) => {} + _ => { + diag.span_label(span, terr.to_string()); + if let Some((sp, msg)) = secondary_span { + diag.span_label(sp, msg); + } + } + }; if let Some((expected, found)) = expected_found { match (terr, is_simple_error, expected == found) { @@ -1169,6 +1176,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { &sort_string(values.found), ); } + (TypeError::ObjectUnsafeCoercion(_), ..) => { + diag.note_unsuccessfull_coercion(found, expected); + } (_, false, _) => { if let Some(exp_found) = exp_found { self.suggest_as_ref_where_appropriate(span, &exp_found, diag); @@ -1267,6 +1277,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let span = trace.cause.span(self.tcx); let failure_code = trace.cause.as_failure_code(terr); let mut diag = match failure_code { + FailureCode::Error0038(did) => { + let violations = self.tcx.object_safety_violations(did); + self.tcx.report_object_safety_error(span, did, violations) + } FailureCode::Error0317(failure_str) => { struct_span_err!(self.tcx.sess, span, E0317, "{}", failure_str) } @@ -1628,6 +1642,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } enum FailureCode { + Error0038(DefId), Error0317(&'static str), Error0580(&'static str), Error0308(&'static str), @@ -1666,6 +1681,7 @@ impl<'tcx> ObligationCause<'tcx> { TypeError::IntrinsicCast => { Error0308("cannot coerce intrinsics to function pointers") } + TypeError::ObjectUnsafeCoercion(did) => Error0038(did.clone()), _ => Error0308("mismatched types"), }, } diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index f4ed7dac1f7c..e385d576b8ce 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -32,7 +32,7 @@ use std::cell::{Cell, Ref, RefCell, RefMut}; use std::collections::BTreeMap; use std::fmt; use syntax::ast; -use syntax_pos::symbol::InternedString; +use syntax_pos::symbol::Symbol; use syntax_pos::Span; use self::combine::CombineFields; @@ -392,7 +392,7 @@ pub enum RegionVariableOrigin { Coercion(Span), /// Region variables created as the values for early-bound regions - EarlyBoundRegion(Span, InternedString), + EarlyBoundRegion(Span, Symbol), /// Region variables created for bound regions /// in a function or method that is called diff --git a/src/librustc/infer/nll_relate/mod.rs b/src/librustc/infer/nll_relate/mod.rs index 64ef0421808f..d6f76e9ee346 100644 --- a/src/librustc/infer/nll_relate/mod.rs +++ b/src/librustc/infer/nll_relate/mod.rs @@ -27,7 +27,8 @@ use crate::ty::error::TypeError; use crate::ty::fold::{TypeFoldable, TypeVisitor}; use crate::ty::relate::{self, Relate, RelateResult, TypeRelation}; use crate::ty::subst::GenericArg; -use crate::ty::{self, Ty, TyCtxt}; +use crate::ty::{self, Ty, TyCtxt, InferConst}; +use crate::infer::{ConstVariableValue, ConstVarValue}; use crate::mir::interpret::ConstValue; use rustc_data_structures::fx::FxHashMap; use std::fmt::Debug; @@ -324,7 +325,7 @@ where let vid = pair.vid(); let value_ty = pair.value_ty(); - // FIXME -- this logic assumes invariance, but that is wrong. + // FIXME(invariance) -- this logic assumes invariance, but that is wrong. // This only presently applies to chalk integration, as NLL // doesn't permit type variables to appear on both sides (and // doesn't use lazy norm). @@ -616,15 +617,21 @@ where fn consts( &mut self, a: &'tcx ty::Const<'tcx>, - b: &'tcx ty::Const<'tcx>, + mut b: &'tcx ty::Const<'tcx>, ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> { - if let ty::Const { val: ConstValue::Bound(..), .. } = a { - // FIXME(const_generics): I'm unsure how this branch should actually be handled, - // so this is probably not correct. - self.infcx.super_combine_consts(self, a, b) - } else { - debug!("consts(a={:?}, b={:?}, variance={:?})", a, b, self.ambient_variance); - relate::super_relate_consts(self, a, b) + let a = self.infcx.shallow_resolve(a); + + if !D::forbid_inference_vars() { + b = self.infcx.shallow_resolve(b); + } + + match b.val { + ConstValue::Infer(InferConst::Var(_)) if D::forbid_inference_vars() => { + // Forbid inference variables in the RHS. + bug!("unexpected inference var {:?}", b) + } + // FIXME(invariance): see the related FIXME above. + _ => self.infcx.super_combine_consts(self, a, b) } } @@ -991,15 +998,28 @@ where a: &'tcx ty::Const<'tcx>, _: &'tcx ty::Const<'tcx>, ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> { - debug!("TypeGeneralizer::consts(a={:?})", a); - - if let ty::Const { val: ConstValue::Bound(..), .. } = a { - bug!( - "unexpected inference variable encountered in NLL generalization: {:?}", - a - ); - } else { - relate::super_relate_consts(self, a, a) + match a.val { + ConstValue::Infer(InferConst::Var(_)) if D::forbid_inference_vars() => { + bug!( + "unexpected inference variable encountered in NLL generalization: {:?}", + a + ); + } + ConstValue::Infer(InferConst::Var(vid)) => { + let mut variable_table = self.infcx.const_unification_table.borrow_mut(); + let var_value = variable_table.probe_value(vid); + match var_value.val.known() { + Some(u) => self.relate(&u, &u), + None => { + let new_var_id = variable_table.new_key(ConstVarValue { + origin: var_value.origin, + val: ConstVariableValue::Unknown { universe: self.universe }, + }); + Ok(self.tcx().mk_const_var(new_var_id, a.ty)) + } + } + } + _ => relate::super_relate_consts(self, a, a), } } diff --git a/src/librustc/infer/type_variable.rs b/src/librustc/infer/type_variable.rs index ce1b54bb1c81..f79a30c7ae8f 100644 --- a/src/librustc/infer/type_variable.rs +++ b/src/librustc/infer/type_variable.rs @@ -1,4 +1,4 @@ -use syntax::symbol::InternedString; +use syntax::symbol::Symbol; use syntax_pos::Span; use crate::ty::{self, Ty, TyVid}; @@ -49,7 +49,7 @@ pub enum TypeVariableOriginKind { MiscVariable, NormalizeProjectionType, TypeInference, - TypeParameterDefinition(InternedString), + TypeParameterDefinition(Symbol), /// One of the upvars or closure kind parameters in a `ClosureSubsts` /// (before it has been determined). diff --git a/src/librustc/infer/unify_key.rs b/src/librustc/infer/unify_key.rs index 846611db0542..b0b6d971c608 100644 --- a/src/librustc/infer/unify_key.rs +++ b/src/librustc/infer/unify_key.rs @@ -3,7 +3,7 @@ use crate::mir::interpret::ConstValue; use rustc_data_structures::unify::{NoError, EqUnifyValue, UnifyKey, UnifyValue, UnificationTable}; use rustc_data_structures::unify::InPlace; use syntax_pos::{Span, DUMMY_SP}; -use syntax::symbol::InternedString; +use syntax::symbol::Symbol; use std::cmp; use std::marker::PhantomData; @@ -90,7 +90,7 @@ pub struct ConstVariableOrigin { pub enum ConstVariableOriginKind { MiscVariable, ConstInference, - ConstParameterDefinition(InternedString), + ConstParameterDefinition(Symbol), SubstitutionPlaceholder, } diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 4c28f6372fe2..15598b60f5c0 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -4,11 +4,12 @@ //! compiler code, rather than using their own custom pass. Those //! lints are all available in `rustc_lint::builtin`. -use crate::lint::{LintPass, LateLintPass, LintArray}; +use crate::lint::{LintPass, LateLintPass, LintArray, FutureIncompatibleInfo}; use crate::middle::stability; use crate::session::Session; use errors::{Applicability, DiagnosticBuilder, pluralise}; use syntax::ast; +use syntax::edition::Edition; use syntax::source_map::Span; use syntax::symbol::Symbol; @@ -22,7 +23,7 @@ declare_lint! { pub CONST_ERR, Deny, "constant evaluation detected erroneous expression", - report_in_external_macro: true + report_in_external_macro } declare_lint! { @@ -71,7 +72,7 @@ declare_lint! { pub UNREACHABLE_CODE, Warn, "detects unreachable code paths", - report_in_external_macro: true + report_in_external_macro } declare_lint! { @@ -131,7 +132,11 @@ declare_lint! { declare_lint! { pub PRIVATE_IN_PUBLIC, Warn, - "detect private items in public interfaces not caught by the old implementation" + "detect private items in public interfaces not caught by the old implementation", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #34537 ", + edition: None, + }; } declare_lint! { @@ -143,13 +148,21 @@ declare_lint! { declare_lint! { pub PUB_USE_OF_PRIVATE_EXTERN_CRATE, Deny, - "detect public re-exports of private extern crates" + "detect public re-exports of private extern crates", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #34537 ", + edition: None, + }; } declare_lint! { pub INVALID_TYPE_PARAM_DEFAULT, Deny, - "type parameter default erroneously allowed in invalid location" + "type parameter default erroneously allowed in invalid location", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #36887 ", + edition: None, + }; } declare_lint! { @@ -161,63 +174,99 @@ declare_lint! { declare_lint! { pub SAFE_EXTERN_STATICS, Deny, - "safe access to extern statics was erroneously allowed" + "safe access to extern statics was erroneously allowed", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #36247 ", + edition: None, + }; } declare_lint! { pub SAFE_PACKED_BORROWS, Warn, - "safe borrows of fields of packed structs were was erroneously allowed" + "safe borrows of fields of packed structs were was erroneously allowed", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #46043 ", + edition: None, + }; } declare_lint! { pub PATTERNS_IN_FNS_WITHOUT_BODY, Warn, - "patterns in functions without body were erroneously allowed" + "patterns in functions without body were erroneously allowed", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #35203 ", + edition: None, + }; } declare_lint! { pub LEGACY_DIRECTORY_OWNERSHIP, Deny, "non-inline, non-`#[path]` modules (e.g., `mod foo;`) were erroneously allowed in some files \ - not named `mod.rs`" + not named `mod.rs`", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #37872 ", + edition: None, + }; } declare_lint! { pub LEGACY_CONSTRUCTOR_VISIBILITY, Deny, - "detects use of struct constructors that would be invisible with new visibility rules" + "detects use of struct constructors that would be invisible with new visibility rules", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #39207 ", + edition: None, + }; } declare_lint! { pub MISSING_FRAGMENT_SPECIFIER, Deny, - "detects missing fragment specifiers in unused `macro_rules!` patterns" + "detects missing fragment specifiers in unused `macro_rules!` patterns", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #40107 ", + edition: None, + }; } declare_lint! { pub PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES, Deny, - "detects parenthesized generic parameters in type and module names" + "detects parenthesized generic parameters in type and module names", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #42238 ", + edition: None, + }; } declare_lint! { pub LATE_BOUND_LIFETIME_ARGUMENTS, Warn, - "detects generic lifetime arguments in path segments with late bound lifetime parameters" + "detects generic lifetime arguments in path segments with late bound lifetime parameters", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #42868 ", + edition: None, + }; } declare_lint! { pub ORDER_DEPENDENT_TRAIT_OBJECTS, Deny, - "trait-object types were treated as different depending on marker-trait order" + "trait-object types were treated as different depending on marker-trait order", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #56484 ", + edition: None, + }; } declare_lint! { pub DEPRECATED, Warn, "detects use of deprecated items", - report_in_external_macro: true + report_in_external_macro } declare_lint! { @@ -253,7 +302,11 @@ declare_lint! { declare_lint! { pub TYVAR_BEHIND_RAW_POINTER, Warn, - "raw pointer to an inference variable" + "raw pointer to an inference variable", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #46906 ", + edition: Some(Edition::Edition2018), + }; } declare_lint! { @@ -272,19 +325,33 @@ declare_lint! { pub ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE, Allow, "fully qualified paths that start with a module name \ - instead of `crate`, `self`, or an extern crate name" + instead of `crate`, `self`, or an extern crate name", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #53130 ", + edition: Some(Edition::Edition2018), + }; } declare_lint! { pub ILLEGAL_FLOATING_POINT_LITERAL_PATTERN, Warn, - "floating-point literals cannot be used in patterns" + "floating-point literals cannot be used in patterns", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #41620 ", + edition: None, + }; } declare_lint! { pub UNSTABLE_NAME_COLLISIONS, Warn, - "detects name collision with an existing but unstable method" + "detects name collision with an existing but unstable method", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #48919 ", + edition: None, + // Note: this item represents future incompatibility of all unstable functions in the + // standard library, and thus should never be removed or changed to an error. + }; } declare_lint! { @@ -302,7 +369,11 @@ declare_lint! { declare_lint! { pub DUPLICATE_MACRO_EXPORTS, Deny, - "detects duplicate macro exports" + "detects duplicate macro exports", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #35896 ", + edition: Some(Edition::Edition2018), + }; } declare_lint! { @@ -326,13 +397,21 @@ declare_lint! { declare_lint! { pub WHERE_CLAUSES_OBJECT_SAFETY, Warn, - "checks the object safety of where clauses" + "checks the object safety of where clauses", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #51443 ", + edition: None, + }; } declare_lint! { pub PROC_MACRO_DERIVE_RESOLUTION_FALLBACK, Warn, - "detects proc macro derives using inaccessible names from parent modules" + "detects proc macro derives using inaccessible names from parent modules", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #50504 ", + edition: None, + }; } declare_lint! { @@ -346,7 +425,11 @@ declare_lint! { pub MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS, Deny, "macro-expanded `macro_export` macros from the current crate \ - cannot be referred to by absolute paths" + cannot be referred to by absolute paths", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #52234 ", + edition: None, + }; } declare_lint! { @@ -359,7 +442,11 @@ declare_lint! { pub INDIRECT_STRUCTURAL_MATCH, // defaulting to allow until rust-lang/rust#62614 is fixed. Allow, - "pattern with const indirectly referencing non-`#[structural_match]` type" + "pattern with const indirectly referencing non-`#[structural_match]` type", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #62411 ", + edition: None, + }; } /// Some lints that are buffered from `libsyntax`. See `syntax::early_buffered_lints`. @@ -367,7 +454,11 @@ pub mod parser { declare_lint! { pub ILL_FORMED_ATTRIBUTE_INPUT, Warn, - "ill-formed attribute inputs that were previously accepted and used in practice" + "ill-formed attribute inputs that were previously accepted and used in practice", + @future_incompatible = super::FutureIncompatibleInfo { + reference: "issue #57571 ", + edition: None, + }; } declare_lint! { @@ -387,31 +478,47 @@ declare_lint! { pub DEPRECATED_IN_FUTURE, Allow, "detects use of items that will be deprecated in a future version", - report_in_external_macro: true + report_in_external_macro } declare_lint! { pub AMBIGUOUS_ASSOCIATED_ITEMS, Deny, - "ambiguous associated items" + "ambiguous associated items", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #57644 ", + edition: None, + }; } declare_lint! { pub NESTED_IMPL_TRAIT, Warn, - "nested occurrence of `impl Trait` type" + "nested occurrence of `impl Trait` type", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #59014 ", + edition: None, + }; } declare_lint! { pub MUTABLE_BORROW_RESERVATION_CONFLICT, Warn, - "reservation of a two-phased borrow conflicts with other shared borrows" + "reservation of a two-phased borrow conflicts with other shared borrows", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #59159 ", + edition: None, + }; } declare_lint! { pub SOFT_UNSTABLE, Deny, - "a feature gate that doesn't break dependent crates" + "a feature gate that doesn't break dependent crates", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #64266 ", + edition: None, + }; } declare_lint_pass! { diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index fa73a3c6c462..1cb53d754dcd 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -22,11 +22,11 @@ use crate::hir::intravisit as hir_visit; use crate::hir::intravisit::Visitor; use crate::hir::map::{definitions::DisambiguatedDefPathData, DefPathData}; use crate::lint::{EarlyLintPass, LateLintPass, EarlyLintPassObject, LateLintPassObject}; -use crate::lint::{LintArray, Level, Lint, LintId, LintPass, LintBuffer}; +use crate::lint::{Level, Lint, LintId, LintPass, LintBuffer, FutureIncompatibleInfo}; use crate::lint::builtin::BuiltinLintDiagnostics; use crate::lint::levels::{LintLevelSets, LintLevelsBuilder}; use crate::middle::privacy::AccessLevels; -use crate::session::{config, early_error, Session}; +use crate::session::Session; use crate::ty::{self, print::Printer, subst::GenericArg, TyCtxt, Ty}; use crate::ty::layout::{LayoutError, LayoutOf, TyLayout}; use crate::util::nodemap::FxHashMap; @@ -35,10 +35,9 @@ use crate::util::common::time; use errors::DiagnosticBuilder; use std::slice; use std::default::Default as StdDefault; -use rustc_data_structures::sync::{ReadGuard, Lock, ParallelIterator, join, par_iter}; +use rustc_data_structures::sync::{self, ParallelIterator, join, par_iter}; use rustc_serialize::{Decoder, Decodable, Encoder, Encodable}; use syntax::ast; -use syntax::edition; use syntax::util::lev_distance::find_best_match_for_name; use syntax::visit as ast_visit; use syntax_pos::{MultiSpan, Span, symbol::Symbol}; @@ -50,24 +49,25 @@ use syntax_pos::{MultiSpan, Span, symbol::Symbol}; pub struct LintStore { /// Registered lints. The bool is true if the lint was /// added by a plugin. - lints: Vec<(&'static Lint, bool)>, + lints: Vec<&'static Lint>, - /// Trait objects for each lint pass. - /// This is only `None` while performing a lint pass. - pre_expansion_passes: Option>, - early_passes: Option>, - late_passes: Lock>>, - late_module_passes: Vec, + /// Constructor functions for each variety of lint pass. + /// + /// These should only be called once, but since we want to avoid locks or + /// interior mutability, we don't enforce this (and lints should, in theory, + /// be compatible with being constructed more than once, though not + /// necessarily in a sane manner. This is safe though.) + pre_expansion_passes: Vec EarlyLintPassObject + sync::Send + sync::Sync>>, + early_passes: Vec EarlyLintPassObject + sync::Send + sync::Sync>>, + late_passes: Vec LateLintPassObject + sync::Send + sync::Sync>>, + /// This is unique in that we construct them per-module, so not once. + late_module_passes: Vec LateLintPassObject + sync::Send + sync::Sync>>, /// Lints indexed by name. by_name: FxHashMap, /// Map of registered lint groups to what lints they expand to. lint_groups: FxHashMap<&'static str, LintGroup>, - - /// Extra info for future incompatibility lints, describing the - /// issue or RFC that caused the incompatibility. - future_incompatible: FxHashMap, } /// Lints that are buffered up early on in the `Session` before the @@ -81,18 +81,6 @@ pub struct BufferedEarlyLint { pub diagnostic: BuiltinLintDiagnostics, } -/// Extra information for a future incompatibility lint. See the call -/// to `register_future_incompatible` in `librustc_lint/lib.rs` for -/// guidelines. -pub struct FutureIncompatibleInfo { - pub id: LintId, - /// e.g., a URL for an issue/PR/RFC or error code - pub reference: &'static str, - /// If this is an edition fixing lint, the edition in which - /// this lint becomes obsolete - pub edition: Option, -} - /// The target of the `by_name` map, which accounts for renaming/deprecation. enum TargetLint { /// A direct lint target @@ -142,17 +130,16 @@ impl LintStore { pub fn new() -> LintStore { LintStore { lints: vec![], - pre_expansion_passes: Some(vec![]), - early_passes: Some(vec![]), - late_passes: Lock::new(Some(vec![])), + pre_expansion_passes: vec![], + early_passes: vec![], + late_passes: vec![], late_module_passes: vec![], by_name: Default::default(), - future_incompatible: Default::default(), lint_groups: Default::default(), } } - pub fn get_lints<'t>(&'t self) -> &'t [(&'static Lint, bool)] { + pub fn get_lints<'t>(&'t self) -> &'t [&'static Lint] { &self.lints } @@ -168,101 +155,66 @@ impl LintStore { .collect() } - pub fn register_early_pass(&mut self, - sess: Option<&Session>, - from_plugin: bool, - register_only: bool, - pass: EarlyLintPassObject) { - self.push_pass(sess, from_plugin, &pass); - if !register_only { - self.early_passes.as_mut().unwrap().push(pass); - } + pub fn register_early_pass( + &mut self, + pass: impl Fn() -> EarlyLintPassObject + 'static + sync::Send + sync::Sync + ) { + self.early_passes.push(Box::new(pass)); } pub fn register_pre_expansion_pass( &mut self, - sess: Option<&Session>, - from_plugin: bool, - register_only: bool, - pass: EarlyLintPassObject, + pass: impl Fn() -> EarlyLintPassObject + 'static + sync::Send + sync::Sync, ) { - self.push_pass(sess, from_plugin, &pass); - if !register_only { - self.pre_expansion_passes.as_mut().unwrap().push(pass); - } + self.pre_expansion_passes.push(Box::new(pass)); } - pub fn register_late_pass(&mut self, - sess: Option<&Session>, - from_plugin: bool, - register_only: bool, - per_module: bool, - pass: LateLintPassObject) { - self.push_pass(sess, from_plugin, &pass); - if !register_only { - if per_module { - self.late_module_passes.push(pass); - } else { - self.late_passes.lock().as_mut().unwrap().push(pass); - } - } + pub fn register_late_pass( + &mut self, + pass: impl Fn() -> LateLintPassObject + 'static + sync::Send + sync::Sync, + ) { + self.late_passes.push(Box::new(pass)); + } + + pub fn register_late_mod_pass( + &mut self, + pass: impl Fn() -> LateLintPassObject + 'static + sync::Send + sync::Sync, + ) { + self.late_module_passes.push(Box::new(pass)); } // Helper method for register_early/late_pass - fn push_pass(&mut self, - sess: Option<&Session>, - from_plugin: bool, - pass: &Box

) { - for lint in pass.get_lints() { - self.lints.push((lint, from_plugin)); + pub fn register_lints(&mut self, lints: &[&'static Lint]) { + for lint in lints { + self.lints.push(lint); let id = LintId::of(lint); if self.by_name.insert(lint.name_lower(), Id(id)).is_some() { - let msg = format!("duplicate specification of lint {}", lint.name_lower()); - match (sess, from_plugin) { - // We load builtin lints first, so a duplicate is a compiler bug. - // Use early_error when handling -W help with no crate. - (None, _) => early_error(config::ErrorOutputType::default(), &msg[..]), - (Some(_), false) => bug!("{}", msg), + bug!("duplicate specification of lint {}", lint.name_lower()) + } - // A duplicate name from a plugin is a user error. - (Some(sess), true) => sess.err(&msg[..]), + if let Some(FutureIncompatibleInfo { edition, .. }) = lint.future_incompatible { + if let Some(edition) = edition { + self.lint_groups.entry(edition.lint_name()) + .or_insert(LintGroup { + lint_ids: vec![], + from_plugin: lint.is_plugin, + depr: None, + }) + .lint_ids.push(id); } + + self.lint_groups.entry("future_incompatible") + .or_insert(LintGroup { + lint_ids: vec![], + from_plugin: lint.is_plugin, + depr: None, + }) + .lint_ids.push(id); } } } - pub fn register_future_incompatible(&mut self, - sess: Option<&Session>, - lints: Vec) { - - for edition in edition::ALL_EDITIONS { - let lints = lints.iter().filter(|f| f.edition == Some(*edition)).map(|f| f.id) - .collect::>(); - if !lints.is_empty() { - self.register_group(sess, false, edition.lint_name(), None, lints) - } - } - - let mut future_incompatible = Vec::with_capacity(lints.len()); - for lint in lints { - future_incompatible.push(lint.id); - self.future_incompatible.insert(lint.id, lint); - } - - self.register_group( - sess, - false, - "future_incompatible", - None, - future_incompatible, - ); - } - - pub fn future_incompatible(&self, id: LintId) -> Option<&FutureIncompatibleInfo> { - self.future_incompatible.get(&id) - } - pub fn register_group_alias( &mut self, lint_name: &'static str, @@ -277,7 +229,6 @@ impl LintStore { pub fn register_group( &mut self, - sess: Option<&Session>, from_plugin: bool, name: &'static str, deprecated_name: Option<&'static str>, @@ -300,16 +251,7 @@ impl LintStore { } if !new { - let msg = format!("duplicate specification of lint group {}", name); - match (sess, from_plugin) { - // We load builtin lints first, so a duplicate is a compiler bug. - // Use early_error when handling -W help with no crate. - (None, _) => early_error(config::ErrorOutputType::default(), &msg[..]), - (Some(_), false) => bug!("{}", msg), - - // A duplicate name from a plugin is a user error. - (Some(sess), true) => sess.err(&msg[..]), - } + bug!("duplicate specification of lint group {}", name); } } @@ -522,7 +464,7 @@ pub struct LateContext<'a, 'tcx> { pub access_levels: &'a AccessLevels, /// The store of registered lints and the lint levels. - lint_store: ReadGuard<'a, LintStore>, + lint_store: &'tcx LintStore, last_node_with_lint_attrs: hir::HirId, @@ -550,7 +492,7 @@ pub struct EarlyContext<'a> { builder: LintLevelsBuilder<'a>, /// The store of registered lints and the lint levels. - lint_store: ReadGuard<'a, LintStore>, + lint_store: &'a LintStore, buffered: LintBuffer, } @@ -639,14 +581,15 @@ pub trait LintContext: Sized { impl<'a> EarlyContext<'a> { fn new( sess: &'a Session, + lint_store: &'a LintStore, krate: &'a ast::Crate, buffered: LintBuffer, ) -> EarlyContext<'a> { EarlyContext { sess, krate, - lint_store: sess.lint_store.borrow(), - builder: LintLevelSets::builder(sess), + lint_store, + builder: LintLevelSets::builder(sess, lint_store), buffered, } } @@ -681,7 +624,7 @@ impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> { f: F) where F: FnOnce(&mut Self) { - let push = self.context.builder.push(attrs); + let push = self.context.builder.push(attrs, &self.context.lint_store); self.check_id(id); self.enter_attrs(attrs); f(self); @@ -875,7 +818,7 @@ impl<'a, 'tcx> LateContext<'a, 'tcx> { _ => {} } - path.push(disambiguated_data.data.as_interned_str().as_symbol()); + path.push(disambiguated_data.data.as_symbol()); Ok(path) } @@ -1355,10 +1298,6 @@ impl LintPass for LateLintPassObjects<'_> { fn name(&self) -> &'static str { panic!() } - - fn get_lints(&self) -> LintArray { - panic!() - } } macro_rules! expand_late_lint_pass_impl_methods { @@ -1393,7 +1332,7 @@ fn late_lint_mod_pass<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>( tables: &ty::TypeckTables::empty(None), param_env: ty::ParamEnv::empty(), access_levels, - lint_store: tcx.sess.lint_store.borrow(), + lint_store: &tcx.lint_store, last_node_with_lint_attrs: tcx.hir().as_local_hir_id(module_def_id).unwrap(), generics: None, only_module: true, @@ -1425,8 +1364,8 @@ pub fn late_lint_mod<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>( late_lint_mod_pass(tcx, module_def_id, builtin_lints); - let mut passes: Vec<_> = tcx.sess.lint_store.borrow().late_module_passes - .iter().map(|pass| pass.fresh_late_pass()).collect(); + let mut passes: Vec<_> = tcx.lint_store.late_module_passes + .iter().map(|pass| (pass)()).collect(); if !passes.is_empty() { late_lint_mod_pass(tcx, module_def_id, LateLintPassObjects { lints: &mut passes[..] }); @@ -1443,7 +1382,7 @@ fn late_lint_pass_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(tcx: TyCtxt<'tc tables: &ty::TypeckTables::empty(None), param_env: ty::ParamEnv::empty(), access_levels, - lint_store: tcx.sess.lint_store.borrow(), + lint_store: &tcx.lint_store, last_node_with_lint_attrs: hir::CRATE_HIR_ID, generics: None, only_module: false, @@ -1467,7 +1406,8 @@ fn late_lint_pass_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(tcx: TyCtxt<'tc } fn late_lint_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(tcx: TyCtxt<'tcx>, builtin_lints: T) { - let mut passes = tcx.sess.lint_store.borrow().late_passes.lock().take().unwrap(); + let mut passes = tcx.lint_store + .late_passes.iter().map(|p| (p)()).collect::>(); if !tcx.sess.opts.debugging_opts.no_interleave_lints { if !passes.is_empty() { @@ -1482,8 +1422,8 @@ fn late_lint_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(tcx: TyCtxt<'tcx>, b }); } - let mut passes: Vec<_> = tcx.sess.lint_store.borrow().late_module_passes - .iter().map(|pass| pass.fresh_late_pass()).collect(); + let mut passes: Vec<_> = tcx.lint_store.late_module_passes + .iter().map(|pass| (pass)()).collect(); for pass in &mut passes { time(tcx.sess, &format!("running late module lint: {}", pass.name()), || { @@ -1491,9 +1431,6 @@ fn late_lint_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(tcx: TyCtxt<'tcx>, b }); } } - - // Put the passes back in the session. - *tcx.sess.lint_store.borrow().late_passes.lock() = Some(passes); } /// Performs lint checking on a crate. @@ -1525,10 +1462,6 @@ impl LintPass for EarlyLintPassObjects<'_> { fn name(&self) -> &'static str { panic!() } - - fn get_lints(&self) -> LintArray { - panic!() - } } macro_rules! expand_early_lint_pass_impl_methods { @@ -1553,12 +1486,13 @@ early_lint_methods!(early_lint_pass_impl, []); fn early_lint_crate( sess: &Session, + lint_store: &LintStore, krate: &ast::Crate, pass: T, buffered: LintBuffer, ) -> LintBuffer { let mut cx = EarlyContextAndPass { - context: EarlyContext::new(sess, krate, buffered), + context: EarlyContext::new(sess, lint_store, krate, buffered), pass, }; @@ -1577,28 +1511,30 @@ fn early_lint_crate( pub fn check_ast_crate( sess: &Session, + lint_store: &LintStore, krate: &ast::Crate, pre_expansion: bool, builtin_lints: T, ) { - let (mut passes, mut buffered) = if pre_expansion { + let (mut passes, mut buffered): (Vec<_>, _) = if pre_expansion { ( - sess.lint_store.borrow_mut().pre_expansion_passes.take().unwrap(), + lint_store.pre_expansion_passes.iter().map(|p| (p)()).collect(), LintBuffer::default(), ) } else { ( - sess.lint_store.borrow_mut().early_passes.take().unwrap(), + lint_store.early_passes.iter().map(|p| (p)()).collect(), sess.buffered_lints.borrow_mut().take().unwrap(), ) }; if !sess.opts.debugging_opts.no_interleave_lints { - buffered = early_lint_crate(sess, krate, builtin_lints, buffered); + buffered = early_lint_crate(sess, lint_store, krate, builtin_lints, buffered); if !passes.is_empty() { buffered = early_lint_crate( sess, + lint_store, krate, EarlyLintPassObjects { lints: &mut passes[..] }, buffered, @@ -1609,6 +1545,7 @@ pub fn check_ast_crate( buffered = time(sess, &format!("running lint: {}", pass.name()), || { early_lint_crate( sess, + lint_store, krate, EarlyLintPassObjects { lints: slice::from_mut(pass) }, buffered, @@ -1617,13 +1554,6 @@ pub fn check_ast_crate( } } - // Put the lint store levels and passes back in the session. - if pre_expansion { - sess.lint_store.borrow_mut().pre_expansion_passes = Some(passes); - } else { - sess.lint_store.borrow_mut().early_passes = Some(passes); - } - // All of the buffered lints should have been emitted at this point. // If not, that means that we somehow buffered a lint for a node id // that was not lint-checked (perhaps it doesn't exist?). This is a bug. @@ -1653,7 +1583,7 @@ impl Decodable for LintId { fn decode(d: &mut D) -> Result { let s = d.read_str()?; ty::tls::with(|tcx| { - match tcx.sess.lint_store.borrow().find_lints(&s) { + match tcx.lint_store.find_lints(&s) { Ok(ids) => { if ids.len() != 0 { panic!("invalid lint-id `{}`", s); diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs index 8ed06cbdc762..4c60492e470c 100644 --- a/src/librustc/lint/levels.rs +++ b/src/librustc/lint/levels.rs @@ -3,7 +3,7 @@ use std::cmp; use crate::hir::HirId; use crate::ich::StableHashingContext; use crate::lint::builtin; -use crate::lint::context::CheckLintNameResult; +use crate::lint::context::{LintStore, CheckLintNameResult}; use crate::lint::{self, Lint, LintId, Level, LintSource}; use crate::session::Session; use crate::util::nodemap::FxHashMap; @@ -35,21 +35,20 @@ enum LintSet { } impl LintLevelSets { - pub fn new(sess: &Session) -> LintLevelSets { + pub fn new(sess: &Session, lint_store: &LintStore) -> LintLevelSets { let mut me = LintLevelSets { list: Vec::new(), lint_cap: Level::Forbid, }; - me.process_command_line(sess); + me.process_command_line(sess, lint_store); return me } - pub fn builder(sess: &Session) -> LintLevelsBuilder<'_> { - LintLevelsBuilder::new(sess, LintLevelSets::new(sess)) + pub fn builder<'a>(sess: &'a Session, store: &LintStore) -> LintLevelsBuilder<'a> { + LintLevelsBuilder::new(sess, LintLevelSets::new(sess, store)) } - fn process_command_line(&mut self, sess: &Session) { - let store = sess.lint_store.borrow(); + fn process_command_line(&mut self, sess: &Session, store: &LintStore) { let mut specs = FxHashMap::default(); self.lint_cap = sess.opts.lint_cap.unwrap_or(Level::Forbid); @@ -186,9 +185,8 @@ impl<'a> LintLevelsBuilder<'a> { /// #[allow] /// /// Don't forget to call `pop`! - pub fn push(&mut self, attrs: &[ast::Attribute]) -> BuilderPush { + pub fn push(&mut self, attrs: &[ast::Attribute], store: &LintStore) -> BuilderPush { let mut specs = FxHashMap::default(); - let store = self.sess.lint_store.borrow(); let sess = self.sess; let bad_attr = |span| { struct_span_err!(sess, span, E0452, "malformed lint attribute input") diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 7443cca822a9..3c35bdae66e9 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -45,7 +45,7 @@ use syntax_pos::Span; pub use crate::lint::context::{LateContext, EarlyContext, LintContext, LintStore, check_crate, check_ast_crate, late_lint_mod, CheckLintNameResult, - FutureIncompatibleInfo, BufferedEarlyLint,}; + BufferedEarlyLint,}; /// Specification of a single lint. #[derive(Copy, Clone, Debug)] @@ -76,9 +76,35 @@ pub struct Lint { /// `true` if this lint is reported even inside expansions of external macros. pub report_in_external_macro: bool, + + pub future_incompatible: Option, + + pub is_plugin: bool, +} + +/// Extra information for a future incompatibility lint. +#[derive(Copy, Clone, Debug)] +pub struct FutureIncompatibleInfo { + /// e.g., a URL for an issue/PR/RFC or error code + pub reference: &'static str, + /// If this is an edition fixing lint, the edition in which + /// this lint becomes obsolete + pub edition: Option, } impl Lint { + pub const fn default_fields_for_macro() -> Self { + Lint { + name: "", + default_level: Level::Forbid, + desc: "", + edition_lint_opts: None, + is_plugin: false, + report_in_external_macro: false, + future_incompatible: None, + } + } + /// Returns the `rust::lint::Lint` for a `syntax::early_buffered_lints::BufferedEarlyLintId`. pub fn from_parser_lint_id(lint_id: BufferedEarlyLintId) -> &'static Self { match lint_id { @@ -105,18 +131,21 @@ impl Lint { #[macro_export] macro_rules! declare_lint { ($vis: vis $NAME: ident, $Level: ident, $desc: expr) => ( - declare_lint!{$vis $NAME, $Level, $desc, false} + declare_lint!( + $vis $NAME, $Level, $desc, + ); ); - ($vis: vis $NAME: ident, $Level: ident, $desc: expr, report_in_external_macro: $rep: expr) => ( - declare_lint!{$vis $NAME, $Level, $desc, $rep} - ); - ($vis: vis $NAME: ident, $Level: ident, $desc: expr, $external: expr) => ( + ($vis: vis $NAME: ident, $Level: ident, $desc: expr, + $(@future_incompatible = $fi:expr;)? $($v:ident),*) => ( $vis static $NAME: &$crate::lint::Lint = &$crate::lint::Lint { name: stringify!($NAME), default_level: $crate::lint::$Level, desc: $desc, edition_lint_opts: None, - report_in_external_macro: $external, + is_plugin: false, + $($v: true,)* + $(future_incompatible: Some($fi),)* + ..$crate::lint::Lint::default_fields_for_macro() }; ); ($vis: vis $NAME: ident, $Level: ident, $desc: expr, @@ -128,6 +157,7 @@ macro_rules! declare_lint { desc: $desc, edition_lint_opts: Some(($lint_edition, $crate::lint::Level::$edition_level)), report_in_external_macro: false, + is_plugin: false, }; ); } @@ -156,6 +186,8 @@ macro_rules! declare_tool_lint { desc: $desc, edition_lint_opts: None, report_in_external_macro: $external, + future_incompatible: None, + is_plugin: true, }; ); } @@ -173,14 +205,6 @@ pub type LintArray = Vec<&'static Lint>; pub trait LintPass { fn name(&self) -> &'static str; - - /// Gets descriptions of the lints this `LintPass` object can emit. - /// - /// N.B., there is no enforcement that the object only emits lints it registered. - /// And some `rustc` internal `LintPass`es register lints to be emitted by other - /// parts of the compiler. If you want enforced access restrictions for your - /// `Lint`, make it a private `static` item in its own module. - fn get_lints(&self) -> LintArray; } /// Implements `LintPass for $name` with the given list of `Lint` statics. @@ -189,7 +213,9 @@ macro_rules! impl_lint_pass { ($name:ident => [$($lint:expr),* $(,)?]) => { impl LintPass for $name { fn name(&self) -> &'static str { stringify!($name) } - fn get_lints(&self) -> LintArray { $crate::lint_array!($($lint),*) } + } + impl $name { + pub fn get_lints() -> LintArray { $crate::lint_array!($($lint),*) } } }; } @@ -287,9 +313,6 @@ macro_rules! expand_lint_pass_methods { macro_rules! declare_late_lint_pass { ([], [$hir:tt], [$($methods:tt)*]) => ( pub trait LateLintPass<'a, $hir>: LintPass { - fn fresh_late_pass(&self) -> LateLintPassObject { - panic!() - } expand_lint_pass_methods!(&LateContext<'a, $hir>, [$($methods)*]); } ) @@ -327,6 +350,12 @@ macro_rules! declare_combined_late_lint_pass { $($passes: $constructor,)* } } + + $v fn get_lints() -> LintArray { + let mut lints = Vec::new(); + $(lints.extend_from_slice(&$passes::get_lints());)* + lints + } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for $name { @@ -337,12 +366,6 @@ macro_rules! declare_combined_late_lint_pass { fn name(&self) -> &'static str { panic!() } - - fn get_lints(&self) -> LintArray { - let mut lints = Vec::new(); - $(lints.extend_from_slice(&self.$passes.get_lints());)* - lints - } } ) } @@ -454,6 +477,12 @@ macro_rules! declare_combined_early_lint_pass { $($passes: $constructor,)* } } + + $v fn get_lints() -> LintArray { + let mut lints = Vec::new(); + $(lints.extend_from_slice(&$passes::get_lints());)* + lints + } } impl EarlyLintPass for $name { @@ -464,12 +493,6 @@ macro_rules! declare_combined_early_lint_pass { fn name(&self) -> &'static str { panic!() } - - fn get_lints(&self) -> LintArray { - let mut lints = Vec::new(); - $(lints.extend_from_slice(&self.$passes.get_lints());)* - lints - } } ) } @@ -649,9 +672,8 @@ pub fn struct_lint_level<'a>(sess: &'a Session, }; // Check for future incompatibility lints and issue a stronger warning. - let lints = sess.lint_store.borrow(); let lint_id = LintId::of(lint); - let future_incompatible = lints.future_incompatible(lint_id); + let future_incompatible = lint.future_incompatible; // If this code originates in a foreign macro, aka something that this crate // did not itself author, then it's likely that there's nothing this crate @@ -755,13 +777,15 @@ pub fn maybe_lint_level_root(tcx: TyCtxt<'_>, id: hir::HirId) -> bool { fn lint_levels(tcx: TyCtxt<'_>, cnum: CrateNum) -> &LintLevelMap { assert_eq!(cnum, LOCAL_CRATE); + let store = &tcx.lint_store; let mut builder = LintLevelMapBuilder { - levels: LintLevelSets::builder(tcx.sess), + levels: LintLevelSets::builder(tcx.sess, &store), tcx: tcx, + store: store, }; let krate = tcx.hir().krate(); - let push = builder.levels.push(&krate.attrs); + let push = builder.levels.push(&krate.attrs, &store); builder.levels.register_id(hir::CRATE_HIR_ID); for macro_def in &krate.exported_macros { builder.levels.register_id(macro_def.hir_id); @@ -772,19 +796,20 @@ fn lint_levels(tcx: TyCtxt<'_>, cnum: CrateNum) -> &LintLevelMap { tcx.arena.alloc(builder.levels.build_map()) } -struct LintLevelMapBuilder<'tcx> { +struct LintLevelMapBuilder<'a, 'tcx> { levels: levels::LintLevelsBuilder<'tcx>, tcx: TyCtxt<'tcx>, + store: &'a LintStore, } -impl LintLevelMapBuilder<'tcx> { +impl LintLevelMapBuilder<'_, '_> { fn with_lint_attrs(&mut self, id: hir::HirId, attrs: &[ast::Attribute], f: F) where F: FnOnce(&mut Self) { - let push = self.levels.push(attrs); + let push = self.levels.push(attrs, self.store); if push.changed { self.levels.register_id(id); } @@ -793,7 +818,7 @@ impl LintLevelMapBuilder<'tcx> { } } -impl intravisit::Visitor<'tcx> for LintLevelMapBuilder<'tcx> { +impl intravisit::Visitor<'tcx> for LintLevelMapBuilder<'_, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'tcx> { intravisit::NestedVisitorMap::All(&self.tcx.hir()) } diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index ec1e32988a60..d5558db2397e 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -16,7 +16,7 @@ use syntax::ast; use syntax::symbol::Symbol; use syntax_pos::Span; use rustc_target::spec::Target; -use rustc_data_structures::sync::{self, MetadataRef, Lrc}; +use rustc_data_structures::sync::{self, MetadataRef}; use rustc_macros::HashStable; pub use self::NativeLibraryKind::*; @@ -191,6 +191,8 @@ pub trait MetadataLoader { -> Result; } +pub type MetadataLoaderDyn = dyn MetadataLoader + Sync; + /// A store of Rust crates, through which their metadata can be accessed. /// /// Note that this trait should probably not be expanding today. All new @@ -201,13 +203,13 @@ pub trait MetadataLoader { /// (it'd break incremental compilation) and should only be called pre-HIR (e.g. /// during resolve) pub trait CrateStore { - fn crate_data_as_rc_any(&self, krate: CrateNum) -> Lrc; + fn crate_data_as_any(&self, cnum: CrateNum) -> &dyn Any; // resolve fn def_key(&self, def: DefId) -> DefKey; fn def_path(&self, def: DefId) -> hir_map::DefPath; fn def_path_hash(&self, def: DefId) -> hir_map::DefPathHash; - fn def_path_table(&self, cnum: CrateNum) -> Lrc; + fn def_path_table(&self, cnum: CrateNum) -> &DefPathTable; // "queries" used in resolve that aren't tracked for incremental compilation fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol; diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index 796d293e2c63..aa8ac4902a89 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -353,11 +353,14 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { &mut self, cx: &impl HasDataLayout, ptr: Pointer, - src: impl IntoIterator, + src: impl IntoIterator, ) -> InterpResult<'tcx> { let mut src = src.into_iter(); - let bytes = self.get_bytes_mut(cx, ptr, Size::from_bytes(src.len() as u64))?; + let (lower, upper) = src.size_hint(); + let len = upper.expect("can only write bounded iterators"); + assert_eq!(lower, len, "can only write iterators with a precise length"); + let bytes = self.get_bytes_mut(cx, ptr, Size::from_bytes(len as u64))?; // `zip` would stop when the first iterator ends; we want to definitely // cover all of `bytes`. for dest in bytes { diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index ccf64c51e133..08e7001681c2 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -37,7 +37,7 @@ use std::slice; use std::vec::IntoIter; use std::{iter, mem, option, u32}; use syntax::ast::Name; -use syntax::symbol::{InternedString, Symbol}; +use syntax::symbol::Symbol; use syntax_pos::{Span, DUMMY_SP}; pub use crate::mir::interpret::AssertMessage; @@ -2736,8 +2736,8 @@ pub enum UnsafetyViolationKind { #[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)] pub struct UnsafetyViolation { pub source_info: SourceInfo, - pub description: InternedString, - pub details: InternedString, + pub description: Symbol, + pub details: Symbol, pub kind: UnsafetyViolationKind, } diff --git a/src/librustc/mir/mono.rs b/src/librustc/mir/mono.rs index eeb997d75ca5..58f99667cb3a 100644 --- a/src/librustc/mir/mono.rs +++ b/src/librustc/mir/mono.rs @@ -1,6 +1,6 @@ use crate::hir::def_id::{DefId, CrateNum, LOCAL_CRATE}; use crate::hir::HirId; -use syntax::symbol::InternedString; +use syntax::symbol::Symbol; use syntax::attr::InlineAttr; use syntax::source_map::Span; use crate::ty::{Instance, InstanceDef, TyCtxt, SymbolName, subst::InternalSubsts}; @@ -80,7 +80,7 @@ impl<'tcx> MonoItem<'tcx> { MonoItem::GlobalAsm(hir_id) => { let def_id = tcx.hir().local_def_id(hir_id); SymbolName { - name: InternedString::intern(&format!("global_asm_{:?}", def_id)) + name: Symbol::intern(&format!("global_asm_{:?}", def_id)) } } } @@ -246,7 +246,7 @@ pub struct CodegenUnit<'tcx> { /// name be unique amongst **all** crates. Therefore, it should /// contain something unique to this crate (e.g., a module path) /// as well as the crate name and disambiguator. - name: InternedString, + name: Symbol, items: FxHashMap, (Linkage, Visibility)>, size_estimate: Option, } @@ -294,7 +294,7 @@ impl_stable_hash_for!(enum self::Visibility { }); impl<'tcx> CodegenUnit<'tcx> { - pub fn new(name: InternedString) -> CodegenUnit<'tcx> { + pub fn new(name: Symbol) -> CodegenUnit<'tcx> { CodegenUnit { name: name, items: Default::default(), @@ -302,11 +302,11 @@ impl<'tcx> CodegenUnit<'tcx> { } } - pub fn name(&self) -> &InternedString { - &self.name + pub fn name(&self) -> Symbol { + self.name } - pub fn set_name(&mut self, name: InternedString) { + pub fn set_name(&mut self, name: Symbol) { self.name = name; } @@ -474,7 +474,7 @@ impl CodegenUnitNameBuilder<'tcx> { cnum: CrateNum, components: I, special_suffix: Option) - -> InternedString + -> Symbol where I: IntoIterator, C: fmt::Display, S: fmt::Display, @@ -487,7 +487,7 @@ impl CodegenUnitNameBuilder<'tcx> { cgu_name } else { let cgu_name = &cgu_name.as_str()[..]; - InternedString::intern(&CodegenUnit::mangle_name(cgu_name)) + Symbol::intern(&CodegenUnit::mangle_name(cgu_name)) } } @@ -497,7 +497,7 @@ impl CodegenUnitNameBuilder<'tcx> { cnum: CrateNum, components: I, special_suffix: Option) - -> InternedString + -> Symbol where I: IntoIterator, C: fmt::Display, S: fmt::Display, @@ -543,6 +543,6 @@ impl CodegenUnitNameBuilder<'tcx> { write!(cgu_name, ".{}", special_suffix).unwrap(); } - InternedString::intern(&cgu_name[..]) + Symbol::intern(&cgu_name[..]) } } diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index 2c407a24493f..fdca6d0e17a1 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -15,7 +15,7 @@ use crate::traits::query::{ }; use std::borrow::Cow; -use syntax_pos::symbol::InternedString; +use syntax_pos::symbol::Symbol; // Each of these queries corresponds to a function pointer field in the // `Providers` struct for requesting a value of that type, and a method @@ -924,7 +924,7 @@ rustc_queries! { desc { "collect_and_partition_mono_items" } } query is_codegened_item(_: DefId) -> bool {} - query codegen_unit(_: InternedString) -> Arc> { + query codegen_unit(_: Symbol) -> Arc> { no_force desc { "codegen_unit" } } diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 2446d4f4788d..33b9ddaa6223 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1149,7 +1149,8 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options, target_cpu: Option = (None, parse_opt_string, [TRACKED], "select target processor (`rustc --print target-cpus` for details)"), target_feature: String = (String::new(), parse_string, [TRACKED], - "target specific attributes (`rustc --print target-features` for details)"), + "target specific attributes. (`rustc --print target-features` for details). \ + This feature is unsafe."), passes: Vec = (Vec::new(), parse_list, [TRACKED], "a list of extra LLVM passes to run (space separated)"), llvm_args: Vec = (Vec::new(), parse_list, [TRACKED], diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index b65bf2230b39..bd2460cfab11 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -14,7 +14,7 @@ use crate::util::common::{duration_to_secs_str, ErrorReported}; use rustc_data_structures::base_n; use rustc_data_structures::sync::{ - self, Lrc, Lock, OneThread, Once, RwLock, AtomicU64, AtomicUsize, Ordering, + self, Lrc, Lock, OneThread, Once, AtomicU64, AtomicUsize, Ordering, Ordering::SeqCst, }; @@ -77,9 +77,11 @@ pub struct Session { /// if the value stored here has been affected by path remapping. pub working_dir: (PathBuf, bool), - // FIXME: `lint_store` and `buffered_lints` are not thread-safe, - // but are only used in a single thread. - pub lint_store: RwLock, + /// This is intended to be used from a single thread. + /// + /// FIXME: there was a previous comment about this not being thread safe, + /// but it's not clear how or why that's the case. The LintBuffer itself is certainly thread + /// safe at least from a "Rust safety" standpoint. pub buffered_lints: Lock>, /// Set of `(DiagnosticId, Option, message)` tuples tracking @@ -1213,7 +1215,6 @@ fn build_session_( sysroot, local_crate_source_file, working_dir, - lint_store: RwLock::new(lint::LintStore::new()), buffered_lints: Lock::new(Some(Default::default())), one_time_diagnostics: Default::default(), plugin_llvm_passes: OneThread::new(RefCell::new(Vec::new())), diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index daa4a215a238..e684cdc0a387 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -406,7 +406,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { }, GenericParamDefKind::Lifetime => continue, }; - let name = param.name.as_symbol(); + let name = param.name; flags.push((name, Some(value))); } @@ -793,15 +793,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ty::Predicate::ObjectSafe(trait_def_id) => { let violations = self.tcx.object_safety_violations(trait_def_id); - if let Some(err) = self.tcx.report_object_safety_error( + self.tcx.report_object_safety_error( span, trait_def_id, violations, - ) { - err - } else { - return; - } + ) } ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => { @@ -937,11 +933,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { TraitNotObjectSafe(did) => { let violations = self.tcx.object_safety_violations(did); - if let Some(err) = self.tcx.report_object_safety_error(span, did, violations) { - err - } else { - return; - } + self.tcx.report_object_safety_error(span, did, violations) } // already reported in the query @@ -1665,11 +1657,7 @@ impl<'tcx> TyCtxt<'tcx> { span: Span, trait_def_id: DefId, violations: Vec, - ) -> Option> { - if self.sess.trait_methods_not_found.borrow().contains(&span) { - // Avoid emitting error caused by non-existing method (#58734) - return None; - } + ) -> DiagnosticBuilder<'tcx> { let trait_str = self.def_path_str(trait_def_id); let span = self.sess.source_map().def_span(span); let mut err = struct_span_err!( @@ -1687,7 +1675,13 @@ impl<'tcx> TyCtxt<'tcx> { }; } } - Some(err) + + if self.sess.trait_methods_not_found.borrow().contains(&span) { + // Avoid emitting error caused by non-existing method (#58734) + err.cancel(); + } + + err } } @@ -2098,6 +2092,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { err.note(&format!("required for the cast to the object type `{}`", self.ty_to_string(object_ty))); } + ObligationCauseCode::Coercion { source: _, target } => { + err.note(&format!("required by cast to type `{}`", + self.ty_to_string(target))); + } ObligationCauseCode::RepeatVec => { err.note("the `Copy` trait is required because the \ repeated element will be copied"); diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index d96330bf0a9b..eb4b114eb301 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -188,6 +188,9 @@ pub enum ObligationCauseCode<'tcx> { /// Obligation incurred due to an object cast. ObjectCastObligation(/* Object type */ Ty<'tcx>), + /// Obligation incurred due to a coercion. + Coercion { source: Ty<'tcx>, target: Ty<'tcx> }, + // Various cases where expressions must be sized/copy/etc: /// L = X implies that L is Sized AssignmentLhsSized, diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index e0ef179911b6..e42c3a63541c 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -19,7 +19,7 @@ use crate::ty::subst::{Subst, InternalSubsts}; use std::borrow::Cow; use std::iter::{self}; use syntax::ast::{self}; -use syntax::symbol::InternedString; +use syntax::symbol::Symbol; use syntax_pos::{Span, DUMMY_SP}; #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] @@ -560,7 +560,7 @@ impl<'tcx> TyCtxt<'tcx> { // are implemented let unsized_self_ty: Ty<'tcx> = self.mk_ty_param( ::std::u32::MAX, - InternedString::intern("RustaceansAreAwesome"), + Symbol::intern("RustaceansAreAwesome"), ); // `Receiver[Self => U]` diff --git a/src/librustc/traits/on_unimplemented.rs b/src/librustc/traits/on_unimplemented.rs index 5a988d9509e8..c1c814f9b037 100644 --- a/src/librustc/traits/on_unimplemented.rs +++ b/src/librustc/traits/on_unimplemented.rs @@ -250,7 +250,7 @@ impl<'tcx> OnUnimplementedFormatString { Position::ArgumentNamed(s) if s == sym::from_desugaring => (), // So is `{A}` if A is a type parameter Position::ArgumentNamed(s) => match generics.params.iter().find(|param| { - param.name.as_symbol() == s + param.name == s }) { Some(_) => (), None => { @@ -289,7 +289,7 @@ impl<'tcx> OnUnimplementedFormatString { }, GenericParamDefKind::Lifetime => return None }; - let name = param.name.as_symbol(); + let name = param.name; Some((name, value)) }).collect::>(); let empty_string = String::new(); diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 44d611ace77d..d8a27f1e0405 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -2246,7 +2246,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } if let Some(principal) = data.principal() { - principal.with_self_ty(self.tcx(), self_ty) + if !self.infcx.tcx.features().object_safe_for_dispatch { + principal.with_self_ty(self.tcx(), self_ty) + } else if self.tcx().is_object_safe(principal.def_id()) { + principal.with_self_ty(self.tcx(), self_ty) + } else { + return; + } } else { // Only auto-trait bounds exist. return; diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index dab62a6bcb5b..18db3c8d10b7 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -4,7 +4,7 @@ use crate::traits; use crate::traits::project::Normalized; use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; use crate::ty::{self, Lift, Ty, TyCtxt}; -use syntax::symbol::InternedString; +use syntax::symbol::Symbol; use std::fmt; use std::rc::Rc; @@ -261,11 +261,11 @@ impl fmt::Display for traits::QuantifierKind { /// for debug output in tests anyway. struct BoundNamesCollector { // Just sort by name because `BoundRegion::BrNamed` does not have a `BoundVar` index anyway. - regions: BTreeSet, + regions: BTreeSet, // Sort by `BoundVar` index, so usually this should be equivalent to the order given // by the list of type parameters. - types: BTreeMap, + types: BTreeMap, binder_index: ty::DebruijnIndex, } @@ -319,7 +319,7 @@ impl<'tcx> TypeVisitor<'tcx> for BoundNamesCollector { match bound_ty.kind { ty::BoundTyKind::Param(name) => name, ty::BoundTyKind::Anon => - InternedString::intern(&format!("^{}", bound_ty.var.as_u32()), + Symbol::intern(&format!("^{}", bound_ty.var.as_u32()), ), } ); @@ -340,7 +340,7 @@ impl<'tcx> TypeVisitor<'tcx> for BoundNamesCollector { } ty::BoundRegion::BrAnon(var) => { - self.regions.insert(InternedString::intern(&format!("'^{}", var))); + self.regions.insert(Symbol::intern(&format!("'^{}", var))); } _ => (), @@ -481,6 +481,10 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> { .and_then(|r| Some(super::ObjectTypeBound(ty, r))) ), super::ObjectCastObligation(ty) => tcx.lift(&ty).map(super::ObjectCastObligation), + super::Coercion { source, target } => Some(super::Coercion { + source: tcx.lift(&source)?, + target: tcx.lift(&target)?, + }), super::AssignmentLhsSized => Some(super::AssignmentLhsSized), super::TupleInitializerSized => Some(super::TupleInitializerSized), super::StructInitializerSized => Some(super::StructInitializerSized), diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index d118bef37fc1..f99298281fec 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -72,7 +72,7 @@ use syntax::ast; use syntax::attr; use syntax::source_map::MultiSpan; use syntax::feature_gate; -use syntax::symbol::{Symbol, InternedString, kw, sym}; +use syntax::symbol::{Symbol, kw, sym}; use syntax_pos::Span; pub struct AllArenas { @@ -949,7 +949,7 @@ impl<'tcx> CommonTypes<'tcx> { f64: mk(Float(ast::FloatTy::F64)), self_param: mk(ty::Param(ty::ParamTy { index: 0, - name: kw::SelfUpper.as_interned_str(), + name: kw::SelfUpper, })), trait_object_dummy_self: mk(Infer(ty::FreshTy(0))), @@ -1027,10 +1027,12 @@ pub struct GlobalCtxt<'tcx> { interners: CtxtInterners<'tcx>, - cstore: &'tcx CrateStoreDyn, + cstore: Box, pub sess: &'tcx Session, + pub lint_store: Lrc, + pub dep_graph: DepGraph, pub prof: SelfProfilerRef, @@ -1192,11 +1194,11 @@ impl<'tcx> TyCtxt<'tcx> { /// reference to the context, to allow formatting values that need it. pub fn create_global_ctxt( s: &'tcx Session, - cstore: &'tcx CrateStoreDyn, + lint_store: Lrc, local_providers: ty::query::Providers<'tcx>, extern_providers: ty::query::Providers<'tcx>, arenas: &'tcx AllArenas, - resolutions: ty::Resolutions, + resolutions: ty::ResolverOutputs, hir: hir_map::Map<'tcx>, on_disk_query_result_cache: query::OnDiskCache<'tcx>, crate_name: &str, @@ -1210,34 +1212,28 @@ impl<'tcx> TyCtxt<'tcx> { let common_lifetimes = CommonLifetimes::new(&interners); let common_consts = CommonConsts::new(&interners, &common_types); let dep_graph = hir.dep_graph.clone(); - let max_cnum = cstore.crates_untracked().iter().map(|c| c.as_usize()).max().unwrap_or(0); + let cstore = resolutions.cstore; + let crates = cstore.crates_untracked(); + let max_cnum = crates.iter().map(|c| c.as_usize()).max().unwrap_or(0); let mut providers = IndexVec::from_elem_n(extern_providers, max_cnum + 1); providers[LOCAL_CRATE] = local_providers; let def_path_hash_to_def_id = if s.opts.build_dep_graph() { - let upstream_def_path_tables: Vec<(CrateNum, Lrc<_>)> = cstore - .crates_untracked() + let def_path_tables = crates .iter() .map(|&cnum| (cnum, cstore.def_path_table(cnum))) - .collect(); - - let def_path_tables = || { - upstream_def_path_tables - .iter() - .map(|&(cnum, ref rc)| (cnum, &**rc)) - .chain(iter::once((LOCAL_CRATE, hir.definitions().def_path_table()))) - }; + .chain(iter::once((LOCAL_CRATE, hir.definitions().def_path_table()))); // Precompute the capacity of the hashmap so we don't have to // re-allocate when populating it. - let capacity = def_path_tables().map(|(_, t)| t.size()).sum::(); + let capacity = def_path_tables.clone().map(|(_, t)| t.size()).sum::(); let mut map: FxHashMap<_, _> = FxHashMap::with_capacity_and_hasher( capacity, ::std::default::Default::default() ); - for (cnum, def_path_table) in def_path_tables() { + for (cnum, def_path_table) in def_path_tables { def_path_table.add_def_path_hashes_to(cnum, &mut map); } @@ -1255,6 +1251,7 @@ impl<'tcx> TyCtxt<'tcx> { GlobalCtxt { sess: s, + lint_store, cstore, arena: WorkerLocal::new(|_| Arena::default()), interners, @@ -1413,8 +1410,8 @@ impl<'tcx> TyCtxt<'tcx> { // Note that this is *untracked* and should only be used within the query // system if the result is otherwise tracked through queries - pub fn crate_data_as_rc_any(self, cnum: CrateNum) -> Lrc { - self.cstore.crate_data_as_rc_any(cnum) + pub fn crate_data_as_any(self, cnum: CrateNum) -> &'tcx dyn Any { + self.cstore.crate_data_as_any(cnum) } #[inline(always)] @@ -1424,7 +1421,7 @@ impl<'tcx> TyCtxt<'tcx> { StableHashingContext::new(self.sess, krate, self.hir().definitions(), - self.cstore) + &*self.cstore) } // This method makes sure that we have a DepNode and a Fingerprint for @@ -2552,7 +2549,7 @@ impl<'tcx> TyCtxt<'tcx> { } #[inline] - pub fn mk_ty_param(self, index: u32, name: InternedString) -> Ty<'tcx> { + pub fn mk_ty_param(self, index: u32, name: Symbol) -> Ty<'tcx> { self.mk_ty(Param(ParamTy { index, name: name })) } @@ -2560,7 +2557,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn mk_const_param( self, index: u32, - name: InternedString, + name: Symbol, ty: Ty<'tcx> ) -> &'tcx Const<'tcx> { self.mk_const(ty::Const { diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index 3395715f67ff..77613b548cfd 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -45,7 +45,7 @@ pub enum TypeError<'tcx> { ProjectionMismatched(ExpectedFound), ProjectionBoundsLength(ExpectedFound), ExistentialMismatch(ExpectedFound<&'tcx ty::List>>), - + ObjectUnsafeCoercion(DefId), ConstMismatch(ExpectedFound<&'tcx ty::Const<'tcx>>), IntrinsicCast, @@ -178,6 +178,7 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { IntrinsicCast => { write!(f, "cannot coerce intrinsics to function pointers") } + ObjectUnsafeCoercion(_) => write!(f, "coercion to object-unsafe trait object"), } } } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index d377b7328e80..4660e8025d48 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -4,7 +4,7 @@ pub use self::Variance::*; pub use self::AssocItemContainer::*; pub use self::BorrowKind::*; pub use self::IntVarValue::*; -pub use self::fold::TypeFoldable; +pub use self::fold::{TypeFoldable, TypeVisitor}; use crate::hir::{map as hir_map, GlobMap, TraitMap}; use crate::hir::Node; @@ -15,6 +15,7 @@ use rustc_macros::HashStable; use crate::ich::Fingerprint; use crate::ich::StableHashingContext; use crate::infer::canonical::Canonical; +use crate::middle::cstore::CrateStoreDyn; use crate::middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem}; use crate::middle::resolve_lifetime::ObjectLifetimeDefault; use crate::mir::Body; @@ -46,11 +47,11 @@ use std::ops::Range; use syntax::ast::{self, Name, Ident, NodeId}; use syntax::attr; use syntax_expand::hygiene::ExpnId; -use syntax::symbol::{kw, sym, Symbol, InternedString}; +use syntax::symbol::{kw, sym, Symbol}; use syntax_pos::Span; use smallvec; -use rustc_data_structures::fx::FxIndexMap; +use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_data_structures::stable_hasher::{StableHasher, HashStable}; use rustc_index::vec::{Idx, IndexVec}; @@ -119,8 +120,9 @@ mod sty; // Data types -#[derive(Clone)] -pub struct Resolutions { +pub struct ResolverOutputs { + pub definitions: hir_map::Definitions, + pub cstore: Box, pub extern_crate_map: NodeMap, pub trait_map: TraitMap, pub maybe_unused_trait_imports: NodeSet, @@ -849,7 +851,7 @@ impl ty::EarlyBoundRegion { /// Does this early bound region have a name? Early bound regions normally /// always have names except when using anonymous lifetimes (`'_`). pub fn has_name(&self) -> bool { - self.name != kw::UnderscoreLifetime.as_interned_str() + self.name != kw::UnderscoreLifetime } } @@ -866,7 +868,7 @@ pub enum GenericParamDefKind { #[derive(Clone, RustcEncodable, RustcDecodable, HashStable)] pub struct GenericParamDef { - pub name: InternedString, + pub name: Symbol, pub def_id: DefId, pub index: u32, @@ -3019,7 +3021,7 @@ impl<'tcx> TyCtxt<'tcx> { }), _ => def_key.disambiguated_data.data.get_opt_name().unwrap_or_else(|| { bug!("item_name: no name for {:?}", self.def_path(id)); - }).as_symbol(), + }), } } } @@ -3393,6 +3395,129 @@ fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync { fn_like.asyncness() } +pub enum NonStructuralMatchTy<'tcx> { + Adt(&'tcx AdtDef), + Param, +} + +/// This method traverses the structure of `ty`, trying to find an +/// instance of an ADT (i.e. struct or enum) that was declared without +/// the `#[structural_match]` attribute, or a generic type parameter +/// (which cannot be determined to be `structural_match`). +/// +/// The "structure of a type" includes all components that would be +/// considered when doing a pattern match on a constant of that +/// type. +/// +/// * This means this method descends into fields of structs/enums, +/// and also descends into the inner type `T` of `&T` and `&mut T` +/// +/// * The traversal doesn't dereference unsafe pointers (`*const T`, +/// `*mut T`), and it does not visit the type arguments of an +/// instantiated generic like `PhantomData`. +/// +/// The reason we do this search is Rust currently require all ADTs +/// reachable from a constant's type to be annotated with +/// `#[structural_match]`, an attribute which essentially says that +/// the implementation of `PartialEq::eq` behaves *equivalently* to a +/// comparison against the unfolded structure. +/// +/// For more background on why Rust has this requirement, and issues +/// that arose when the requirement was not enforced completely, see +/// Rust RFC 1445, rust-lang/rust#61188, and rust-lang/rust#62307. +pub fn search_for_structural_match_violation<'tcx>( + tcx: TyCtxt<'tcx>, + ty: Ty<'tcx>, +) -> Option> { + let mut search = Search { tcx, found: None, seen: FxHashSet::default() }; + ty.visit_with(&mut search); + return search.found; + + struct Search<'tcx> { + tcx: TyCtxt<'tcx>, + + // Records the first ADT or type parameter we find without `#[structural_match`. + found: Option>, + + // Tracks ADTs previously encountered during search, so that + // we will not recurse on them again. + seen: FxHashSet, + } + + impl<'tcx> TypeVisitor<'tcx> for Search<'tcx> { + fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { + debug!("Search visiting ty: {:?}", ty); + + let (adt_def, substs) = match ty.kind { + ty::Adt(adt_def, substs) => (adt_def, substs), + ty::Param(_) => { + self.found = Some(NonStructuralMatchTy::Param); + return true; // Stop visiting. + } + ty::RawPtr(..) => { + // `#[structural_match]` ignores substructure of + // `*const _`/`*mut _`, so skip super_visit_with + // + // (But still tell caller to continue search.) + return false; + } + ty::FnDef(..) | ty::FnPtr(..) => { + // types of formals and return in `fn(_) -> _` are also irrelevant + // + // (But still tell caller to continue search.) + return false; + } + ty::Array(_, n) if n.try_eval_usize(self.tcx, ty::ParamEnv::reveal_all()) == Some(0) + => { + // rust-lang/rust#62336: ignore type of contents + // for empty array. + return false; + } + _ => { + ty.super_visit_with(self); + return false; + } + }; + + if !self.tcx.has_attr(adt_def.did, sym::structural_match) { + self.found = Some(NonStructuralMatchTy::Adt(&adt_def)); + debug!("Search found adt_def: {:?}", adt_def); + return true; // Stop visiting. + } + + if !self.seen.insert(adt_def.did) { + debug!("Search already seen adt_def: {:?}", adt_def); + // let caller continue its search + return false; + } + + // `#[structural_match]` does not care about the + // instantiation of the generics in an ADT (it + // instead looks directly at its fields outside + // this match), so we skip super_visit_with. + // + // (Must not recur on substs for `PhantomData` cf + // rust-lang/rust#55028 and rust-lang/rust#55837; but also + // want to skip substs when only uses of generic are + // behind unsafe pointers `*const T`/`*mut T`.) + + // even though we skip super_visit_with, we must recur on + // fields of ADT. + let tcx = self.tcx; + for field_ty in adt_def.all_fields().map(|field| field.ty(tcx, substs)) { + if field_ty.visit_with(self) { + // found an ADT without `#[structural_match]`; halt visiting! + assert!(self.found.is_some()); + return true; + } + } + + // Even though we do not want to recur on substs, we do + // want our caller to continue its own search. + false + } + } +} pub fn provide(providers: &mut ty::query::Providers<'_>) { context::provide(providers); @@ -3429,11 +3554,11 @@ pub struct CrateInherentImpls { pub inherent_impls: DefIdMap>, } -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable)] +#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable)] pub struct SymbolName { // FIXME: we don't rely on interning or equality here - better have // this be a `&'tcx str`. - pub name: InternedString + pub name: Symbol } impl_stable_hash_for!(struct self::SymbolName { @@ -3443,11 +3568,24 @@ impl_stable_hash_for!(struct self::SymbolName { impl SymbolName { pub fn new(name: &str) -> SymbolName { SymbolName { - name: InternedString::intern(name) + name: Symbol::intern(name) } } } +impl PartialOrd for SymbolName { + fn partial_cmp(&self, other: &SymbolName) -> Option { + self.name.as_str().partial_cmp(&other.name.as_str()) + } +} + +/// Ordering must use the chars to ensure reproducible builds. +impl Ord for SymbolName { + fn cmp(&self, other: &SymbolName) -> Ordering { + self.name.as_str().cmp(&other.name.as_str()) + } +} + impl fmt::Display for SymbolName { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(&self.name, fmt) diff --git a/src/librustc/ty/print/obsolete.rs b/src/librustc/ty/print/obsolete.rs index df39d0ccc9ee..e72916de6a9c 100644 --- a/src/librustc/ty/print/obsolete.rs +++ b/src/librustc/ty/print/obsolete.rs @@ -218,9 +218,9 @@ impl DefPathBasedNames<'tcx> { // foo::bar::ItemName:: for part in self.tcx.def_path(def_id).data { if self.omit_disambiguators { - write!(output, "{}::", part.data.as_interned_str()).unwrap(); + write!(output, "{}::", part.data.as_symbol()).unwrap(); } else { - write!(output, "{}[{}]::", part.data.as_interned_str(), part.disambiguator) + write!(output, "{}[{}]::", part.data.as_symbol(), part.disambiguator) .unwrap(); } } diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 363109a0582d..8a98a5d83615 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -14,7 +14,7 @@ use rustc_apfloat::Float; use rustc_target::spec::abi::Abi; use syntax::ast; use syntax::attr::{SignedInt, UnsignedInt}; -use syntax::symbol::{kw, InternedString}; +use syntax::symbol::{kw, Symbol}; use std::cell::Cell; use std::fmt::{self, Write as _}; @@ -384,7 +384,7 @@ pub trait PrettyPrinter<'tcx>: let reexport = self.tcx().item_children(visible_parent) .iter() .find(|child| child.res.def_id() == def_id) - .map(|child| child.ident.as_interned_str()); + .map(|child| child.ident.name); if let Some(reexport) = reexport { *name = reexport; } @@ -392,7 +392,7 @@ pub trait PrettyPrinter<'tcx>: // Re-exported `extern crate` (#43189). DefPathData::CrateRoot => { data = DefPathData::TypeNs( - self.tcx().original_crate_name(def_id.krate).as_interned_str(), + self.tcx().original_crate_name(def_id.krate), ); } _ => {} @@ -992,7 +992,7 @@ pub struct FmtPrinterData<'a, 'tcx, F> { empty_path: bool, in_value: bool, - used_region_names: FxHashSet, + used_region_names: FxHashSet, region_index: usize, binder_depth: usize, @@ -1222,7 +1222,7 @@ impl Printer<'tcx> for FmtPrinter<'_, 'tcx, F> { // FIXME(eddyb) `name` should never be empty, but it // currently is for `extern { ... }` "foreign modules". - let name = disambiguated_data.data.as_interned_str().as_str(); + let name = disambiguated_data.data.as_symbol().as_str(); if !name.is_empty() { if !self.empty_path { write!(self, "::")?; @@ -1332,16 +1332,16 @@ impl PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx, F> { match *region { ty::ReEarlyBound(ref data) => { - data.name.as_symbol() != kw::Invalid && - data.name.as_symbol() != kw::UnderscoreLifetime + data.name != kw::Invalid && + data.name != kw::UnderscoreLifetime } ty::ReLateBound(_, br) | ty::ReFree(ty::FreeRegion { bound_region: br, .. }) | ty::RePlaceholder(ty::Placeholder { name: br, .. }) => { if let ty::BrNamed(_, name) = br { - if name.as_symbol() != kw::Invalid && - name.as_symbol() != kw::UnderscoreLifetime { + if name != kw::Invalid && + name != kw::UnderscoreLifetime { return true; } } @@ -1397,7 +1397,7 @@ impl FmtPrinter<'_, '_, F> { // `explain_region()` or `note_and_explain_region()`. match *region { ty::ReEarlyBound(ref data) => { - if data.name.as_symbol() != kw::Invalid { + if data.name != kw::Invalid { p!(write("{}", data.name)); return Ok(self); } @@ -1406,8 +1406,8 @@ impl FmtPrinter<'_, '_, F> { ty::ReFree(ty::FreeRegion { bound_region: br, .. }) | ty::RePlaceholder(ty::Placeholder { name: br, .. }) => { if let ty::BrNamed(_, name) = br { - if name.as_symbol() != kw::Invalid && - name.as_symbol() != kw::UnderscoreLifetime { + if name != kw::Invalid && + name != kw::UnderscoreLifetime { p!(write("{}", name)); return Ok(self); } @@ -1474,11 +1474,11 @@ impl FmtPrinter<'_, 'tcx, F> { where T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>, { - fn name_by_region_index(index: usize) -> InternedString { + fn name_by_region_index(index: usize) -> Symbol { match index { - 0 => InternedString::intern("'r"), - 1 => InternedString::intern("'s"), - i => InternedString::intern(&format!("'t{}", i-2)), + 0 => Symbol::intern("'r"), + 1 => Symbol::intern("'s"), + i => Symbol::intern(&format!("'t{}", i-2)), } } @@ -1541,7 +1541,7 @@ impl FmtPrinter<'_, 'tcx, F> { where T: TypeFoldable<'tcx> { - struct LateBoundRegionNameCollector<'a>(&'a mut FxHashSet); + struct LateBoundRegionNameCollector<'a>(&'a mut FxHashSet); impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector<'_> { fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool { match *r { diff --git a/src/librustc/ty/query/keys.rs b/src/librustc/ty/query/keys.rs index f61801cd2327..0a217e9ae666 100644 --- a/src/librustc/ty/query/keys.rs +++ b/src/librustc/ty/query/keys.rs @@ -9,7 +9,7 @@ use crate::ty::fast_reject::SimplifiedType; use crate::mir; use syntax_pos::{Span, DUMMY_SP}; -use syntax_pos::symbol::InternedString; +use syntax_pos::symbol::Symbol; /// The `Key` trait controls what types can legally be used as the key /// for a query. @@ -188,7 +188,7 @@ impl<'tcx> Key for traits::Environment<'tcx> { } } -impl Key for InternedString { +impl Key for Symbol { fn query_crate(&self) -> CrateNum { LOCAL_CRATE } diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index 4279ca8c3daf..9b15ad560b5d 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -55,7 +55,6 @@ use std::ops::Deref; use std::sync::Arc; use std::any::type_name; use syntax_pos::{Span, DUMMY_SP}; -use syntax_pos::symbol::InternedString; use syntax::attr; use syntax::ast; use syntax::feature_gate; diff --git a/src/librustc/ty/query/values.rs b/src/librustc/ty/query/values.rs index 0149f7571647..f0d1639f72f5 100644 --- a/src/librustc/ty/query/values.rs +++ b/src/librustc/ty/query/values.rs @@ -1,7 +1,7 @@ use crate::ty::{self, Ty, TyCtxt, AdtSizedConstraint}; use crate::ty::util::NeedsDrop; -use syntax::symbol::InternedString; +use syntax::symbol::Symbol; pub(super) trait Value<'tcx>: Sized { fn from_cycle_error(tcx: TyCtxt<'tcx>) -> Self; @@ -22,7 +22,7 @@ impl<'tcx> Value<'tcx> for Ty<'tcx> { impl<'tcx> Value<'tcx> for ty::SymbolName { fn from_cycle_error(_: TyCtxt<'tcx>) -> Self { - ty::SymbolName { name: InternedString::intern("") } + ty::SymbolName { name: Symbol::intern("") } } } diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 41f34703622e..1da65f4b51d3 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -557,10 +557,9 @@ pub fn super_relate_consts>( x.val }; - // Currently, the values that can be unified are those that - // implement both `PartialEq` and `Eq`, corresponding to - // `structural_match` types. - // FIXME(const_generics): check for `structural_match` synthetic attribute. + // Currently, the values that can be unified are primitive types, + // and those that derive both `PartialEq` and `Eq`, corresponding + // to `structural_match` types. let new_const_val = match (eagerly_eval(a), eagerly_eval(b)) { (ConstValue::Infer(_), _) | (_, ConstValue::Infer(_)) => { // The caller should handle these cases! diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 6b1f10bdb21c..5d78d563e9a4 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -749,6 +749,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::error::TypeError<'a> { ExistentialMismatch(ref x) => return tcx.lift(x).map(ExistentialMismatch), ConstMismatch(ref x) => return tcx.lift(x).map(ConstMismatch), IntrinsicCast => IntrinsicCast, + ObjectUnsafeCoercion(ref x) => return tcx.lift(x).map(ObjectUnsafeCoercion), }) } } @@ -1350,6 +1351,7 @@ EnumTypeFoldableImpl! { (ty::error::TypeError::ExistentialMismatch)(x), (ty::error::TypeError::ConstMismatch)(x), (ty::error::TypeError::IntrinsicCast), + (ty::error::TypeError::ObjectUnsafeCoercion)(x), } } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 298e79895963..3a9994ac64c7 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -24,7 +24,7 @@ use std::marker::PhantomData; use std::ops::Range; use rustc_target::spec::abi; use syntax::ast::{self, Ident}; -use syntax::symbol::{kw, InternedString}; +use syntax::symbol::{kw, Symbol}; use self::InferTy::*; use self::TyKind::*; @@ -55,7 +55,7 @@ pub enum BoundRegion { /// /// The `DefId` is needed to distinguish free regions in /// the event of shadowing. - BrNamed(DefId, InternedString), + BrNamed(DefId, Symbol), /// Anonymous region for the implicit env pointer parameter /// to a closure @@ -1121,16 +1121,16 @@ pub type CanonicalPolyFnSig<'tcx> = Canonical<'tcx, Binder>>; Hash, RustcEncodable, RustcDecodable, HashStable)] pub struct ParamTy { pub index: u32, - pub name: InternedString, + pub name: Symbol, } impl<'tcx> ParamTy { - pub fn new(index: u32, name: InternedString) -> ParamTy { + pub fn new(index: u32, name: Symbol) -> ParamTy { ParamTy { index, name: name } } pub fn for_self() -> ParamTy { - ParamTy::new(0, kw::SelfUpper.as_interned_str()) + ParamTy::new(0, kw::SelfUpper) } pub fn for_def(def: &ty::GenericParamDef) -> ParamTy { @@ -1146,11 +1146,11 @@ impl<'tcx> ParamTy { Eq, PartialEq, Ord, PartialOrd, HashStable)] pub struct ParamConst { pub index: u32, - pub name: InternedString, + pub name: Symbol, } impl<'tcx> ParamConst { - pub fn new(index: u32, name: InternedString) -> ParamConst { + pub fn new(index: u32, name: Symbol) -> ParamConst { ParamConst { index, name } } @@ -1323,7 +1323,7 @@ impl<'tcx> rustc_serialize::UseSpecializedDecodable for Region<'tcx> {} pub struct EarlyBoundRegion { pub def_id: DefId, pub index: u32, - pub name: InternedString, + pub name: Symbol, } #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] @@ -1387,7 +1387,7 @@ pub struct BoundTy { #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] pub enum BoundTyKind { Anon, - Param(InternedString), + Param(Symbol), } impl_stable_hash_for!(struct BoundTy { var, kind }); diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index ecb075e30b14..b50e819c956e 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -380,16 +380,21 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { // obligations that don't refer to Self and // checking those - let cause = self.cause(traits::MiscObligation); - let component_traits = - data.auto_traits().chain(data.principal_def_id()); - self.out.extend( - component_traits.map(|did| traits::Obligation::new( - cause.clone(), - param_env, - ty::Predicate::ObjectSafe(did) - )) - ); + let defer_to_coercion = + self.infcx.tcx.features().object_safe_for_dispatch; + + if !defer_to_coercion { + let cause = self.cause(traits::MiscObligation); + let component_traits = + data.auto_traits().chain(data.principal_def_id()); + self.out.extend( + component_traits.map(|did| traits::Obligation::new( + cause.clone(), + param_env, + ty::Predicate::ObjectSafe(did) + )) + ); + } } // Inference variables are the complicated case, since we don't diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs index bd7d0d4017dc..edd34b52eade 100644 --- a/src/librustc_codegen_llvm/base.rs +++ b/src/librustc_codegen_llvm/base.rs @@ -36,7 +36,7 @@ use rustc_codegen_ssa::back::write::submit_codegened_module_to_llvm; use std::ffi::CString; use std::time::Instant; -use syntax_pos::symbol::InternedString; +use syntax_pos::symbol::Symbol; use rustc::hir::CodegenFnAttrs; use crate::value::Value; @@ -105,7 +105,7 @@ pub fn iter_globals(llmod: &'ll llvm::Module) -> ValueIter<'ll> { pub fn compile_codegen_unit( tcx: TyCtxt<'tcx>, - cgu_name: InternedString, + cgu_name: Symbol, tx_to_llvm_workers: &std::sync::mpsc::Sender>, ) { let prof_timer = tcx.prof.generic_activity("codegen_module"); @@ -131,7 +131,7 @@ pub fn compile_codegen_unit( fn module_codegen( tcx: TyCtxt<'_>, - cgu_name: InternedString, + cgu_name: Symbol, ) -> ModuleCodegen { let cgu = tcx.codegen_unit(cgu_name); // Instantiate monomorphizations without filling out definitions yet... diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs index d4df5b4a804e..fd7054a5a0ad 100644 --- a/src/librustc_codegen_llvm/consts.rs +++ b/src/librustc_codegen_llvm/consts.rs @@ -221,7 +221,7 @@ impl CodegenCx<'ll, 'tcx> { def_id); let ty = instance.ty(self.tcx); - let sym = self.tcx.symbol_name(instance).name.as_symbol(); + let sym = self.tcx.symbol_name(instance).name; debug!("get_static: sym={} instance={:?}", sym, instance); diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 7bd82ced3c38..f0148a21ae67 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -46,7 +46,7 @@ use std::iter; use std::ptr; use std::path::{Path, PathBuf}; use syntax::ast; -use syntax::symbol::{Interner, InternedString}; +use syntax::symbol::{Interner, Symbol}; use syntax_pos::{self, Span, FileName}; impl PartialEq for llvm::Metadata { @@ -2125,7 +2125,7 @@ fn compute_type_parameters(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>) -> Option<&' fn get_parameter_names(cx: &CodegenCx<'_, '_>, generics: &ty::Generics) - -> Vec { + -> Vec { let mut names = generics.parent.map_or(vec![], |def_id| { get_parameter_names(cx, cx.tcx.generics_of(def_id)) }); diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs index 6e4ed42c45e9..5b59f4c28de2 100644 --- a/src/librustc_codegen_llvm/debuginfo/mod.rs +++ b/src/librustc_codegen_llvm/debuginfo/mod.rs @@ -36,7 +36,7 @@ use std::ffi::{CStr, CString}; use syntax_pos::{self, Span, Pos}; use syntax::ast; -use syntax::symbol::InternedString; +use syntax::symbol::Symbol; use rustc::ty::layout::{self, LayoutOf, HasTyCtxt}; use rustc_codegen_ssa::traits::*; @@ -490,7 +490,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn get_parameter_names(cx: &CodegenCx<'_, '_>, generics: &ty::Generics) - -> Vec { + -> Vec { let mut names = generics.parent.map_or(vec![], |def_id| { get_parameter_names(cx, cx.tcx.generics_of(def_id)) }); diff --git a/src/librustc_codegen_llvm/debuginfo/namespace.rs b/src/librustc_codegen_llvm/debuginfo/namespace.rs index 889984749fdf..628d1372b570 100644 --- a/src/librustc_codegen_llvm/debuginfo/namespace.rs +++ b/src/librustc_codegen_llvm/debuginfo/namespace.rs @@ -35,7 +35,7 @@ pub fn item_namespace(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DIScope { let namespace_name = match def_key.disambiguated_data.data { DefPathData::CrateRoot => cx.tcx.crate_name(def_id.krate).as_str(), - data => data.as_interned_str().as_str() + data => data.as_symbol().as_str() }; let namespace_name = SmallCStr::new(&namespace_name); diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs index 9b55bef0c514..e09b600afd4e 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -50,14 +50,13 @@ use rustc_codegen_ssa::CompiledModule; use errors::{FatalError, Handler}; use rustc::dep_graph::WorkProduct; use syntax_expand::allocator::AllocatorKind; -use syntax_pos::symbol::InternedString; pub use llvm_util::target_features; use std::any::Any; use std::sync::Arc; use std::ffi::CStr; use rustc::dep_graph::DepGraph; -use rustc::middle::cstore::{EncodedMetadata, MetadataLoader}; +use rustc::middle::cstore::{EncodedMetadata, MetadataLoaderDyn}; use rustc::session::Session; use rustc::session::config::{OutputFilenames, OutputType, PrintRequest, OptLevel}; use rustc::ty::{self, TyCtxt}; @@ -123,7 +122,7 @@ impl ExtraBackendMethods for LlvmCodegenBackend { } fn compile_codegen_unit( &self, tcx: TyCtxt<'_>, - cgu_name: InternedString, + cgu_name: Symbol, tx: &std::sync::mpsc::Sender>, ) { base::compile_codegen_unit(tcx, cgu_name, tx); @@ -261,7 +260,7 @@ impl CodegenBackend for LlvmCodegenBackend { target_features(sess) } - fn metadata_loader(&self) -> Box { + fn metadata_loader(&self) -> Box { box metadata::LlvmMetadataLoader } diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index 8bc815f2c622..762b50f1659c 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -259,7 +259,7 @@ fn generate_lto_work( needs_thin_lto: Vec<(String, B::ThinBuffer)>, import_only_modules: Vec<(SerializedModule, WorkProduct)> ) -> Vec<(WorkItem, u64)> { - let _prof_timer = cgcx.prof.generic_activity("codegen_run_lto"); + let _prof_timer = cgcx.prof.generic_activity("codegen_generate_lto_work"); let (lto_modules, copy_jobs) = if !needs_fat_lto.is_empty() { assert!(needs_thin_lto.is_empty()); @@ -674,11 +674,11 @@ impl WorkItem { } } - pub fn name(&self) -> String { + fn profiling_event_id(&self) -> &'static str { match *self { - WorkItem::Optimize(ref m) => format!("optimize: {}", m.name), - WorkItem::CopyPostLtoArtifacts(ref m) => format!("copy post LTO artifacts: {}", m.name), - WorkItem::LTO(ref m) => format!("lto: {}", m.name()), + WorkItem::Optimize(_) => "codegen_module_optimize", + WorkItem::CopyPostLtoArtifacts(_) => "codegen_copy_artifacts_from_incr_cache", + WorkItem::LTO(_) => "codegen_module_perform_lto", } } } @@ -1587,7 +1587,7 @@ fn spawn_work( // as a diagnostic was already sent off to the main thread - just // surface that there was an error in this worker. bomb.result = { - let _prof_timer = cgcx.prof.generic_activity(&work.name()); + let _prof_timer = cgcx.prof.generic_activity(work.profiling_event_id()); execute_work_item(&cgcx, work).ok() }; }); diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index f4f3dd4d2d29..bf687f846357 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -406,6 +406,8 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(cx: &' rust_main_def_id: DefId, use_start_lang_item: bool, ) { + // The entry function is either `int main(void)` or `int main(int argc, char **argv)`, + // depending on whether the target needs `argc` and `argv` to be passed in. let llfty = if cx.sess().target.target.options.main_needs_argc_argv { cx.type_func(&[cx.type_int(), cx.type_ptr_to(cx.type_i8p())], cx.type_int()) } else { @@ -440,19 +442,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(cx: &' bx.insert_reference_to_gdb_debug_scripts_section_global(); - let (arg_argc, arg_argv) = if cx.sess().target.target.options.main_needs_argc_argv { - // Params from native main() used as args for rust start function - let param_argc = bx.get_param(0); - let param_argv = bx.get_param(1); - let arg_argc = bx.intcast(param_argc, cx.type_isize(), true); - let arg_argv = param_argv; - (arg_argc, arg_argv) - } else { - // The Rust start function doesn't need argc and argv, so just pass zeros. - let arg_argc = bx.const_int(cx.type_int(), 0); - let arg_argv = bx.const_null(cx.type_ptr_to(cx.type_i8p())); - (arg_argc, arg_argv) - }; + let (arg_argc, arg_argv) = get_argc_argv(cx, &mut bx); let (start_fn, args) = if use_start_lang_item { let start_def_id = cx.tcx().require_lang_item(StartFnLangItem, None); @@ -477,6 +467,27 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(cx: &' } } +/// Obtain the `argc` and `argv` values to pass to the rust start function. +fn get_argc_argv<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( + cx: &'a Bx::CodegenCx, + bx: &mut Bx +) -> (Bx::Value, Bx::Value) +{ + if cx.sess().target.target.options.main_needs_argc_argv { + // Params from native `main()` used as args for rust start function + let param_argc = bx.get_param(0); + let param_argv = bx.get_param(1); + let arg_argc = bx.intcast(param_argc, cx.type_isize(), true); + let arg_argv = param_argv; + (arg_argc, arg_argv) + } else { + // The Rust start function doesn't need `argc` and `argv`, so just pass zeros. + let arg_argc = bx.const_int(cx.type_int(), 0); + let arg_argv = bx.const_null(cx.type_ptr_to(cx.type_i8p())); + (arg_argc, arg_argv) + } +} + pub const CODEGEN_WORKER_ID: usize = ::std::usize::MAX; pub fn codegen_crate( @@ -515,7 +526,7 @@ pub fn codegen_crate( // unnecessarily. if tcx.dep_graph.is_fully_enabled() { for cgu in &codegen_units { - tcx.codegen_unit(cgu.name().clone()); + tcx.codegen_unit(cgu.name()); } } @@ -603,7 +614,7 @@ pub fn codegen_crate( match cgu_reuse { CguReuse::No => { let start_time = Instant::now(); - backend.compile_codegen_unit(tcx, *cgu.name(), &ongoing_codegen.coordinator_send); + backend.compile_codegen_unit(tcx, cgu.name(), &ongoing_codegen.coordinator_send); total_codegen_time += start_time.elapsed(); false } diff --git a/src/librustc_codegen_ssa/debuginfo/type_names.rs b/src/librustc_codegen_ssa/debuginfo/type_names.rs index d875c60959cb..166a74fe4879 100644 --- a/src/librustc_codegen_ssa/debuginfo/type_names.rs +++ b/src/librustc_codegen_ssa/debuginfo/type_names.rs @@ -221,7 +221,7 @@ pub fn push_debuginfo_type_name<'tcx>( output.push_str(&tcx.crate_name(def_id.krate).as_str()); for path_element in tcx.def_path(def_id).data { output.push_str("::"); - output.push_str(&path_element.data.as_interned_str().as_str()); + output.push_str(&path_element.data.as_symbol().as_str()); } } else { output.push_str(&tcx.item_name(def_id).as_str()); diff --git a/src/librustc_codegen_ssa/traits/backend.rs b/src/librustc_codegen_ssa/traits/backend.rs index 7cae3e9ade59..1fff740d7403 100644 --- a/src/librustc_codegen_ssa/traits/backend.rs +++ b/src/librustc_codegen_ssa/traits/backend.rs @@ -10,7 +10,7 @@ use rustc_codegen_utils::codegen_backend::CodegenBackend; use std::sync::Arc; use std::sync::mpsc; use syntax_expand::allocator::AllocatorKind; -use syntax_pos::symbol::InternedString; +use syntax_pos::symbol::Symbol; pub trait BackendTypes { type Value: CodegenObject; @@ -50,7 +50,7 @@ pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Se fn compile_codegen_unit( &self, tcx: TyCtxt<'_>, - cgu_name: InternedString, + cgu_name: Symbol, tx_to_llvm_workers: &mpsc::Sender>, ); // If find_features is true this won't access `sess.crate_types` by assuming diff --git a/src/librustc_codegen_utils/codegen_backend.rs b/src/librustc_codegen_utils/codegen_backend.rs index 1077c1f42637..0e2c3731eae6 100644 --- a/src/librustc_codegen_utils/codegen_backend.rs +++ b/src/librustc_codegen_utils/codegen_backend.rs @@ -14,7 +14,7 @@ use rustc::util::common::ErrorReported; use rustc::session::config::{OutputFilenames, PrintRequest}; use rustc::ty::TyCtxt; use rustc::ty::query::Providers; -use rustc::middle::cstore::{EncodedMetadata, MetadataLoader}; +use rustc::middle::cstore::{EncodedMetadata, MetadataLoaderDyn}; use rustc::dep_graph::DepGraph; pub use rustc_data_structures::sync::MetadataRef; @@ -26,7 +26,7 @@ pub trait CodegenBackend { fn print_passes(&self) {} fn print_version(&self) {} - fn metadata_loader(&self) -> Box; + fn metadata_loader(&self) -> Box; fn provide(&self, _providers: &mut Providers<'_>); fn provide_extern(&self, _providers: &mut Providers<'_>); fn codegen_crate<'tcx>( diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index 7ccd024769f7..c52c6cfa83c9 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -95,7 +95,7 @@ use rustc::ty::query::Providers; use rustc::ty::{self, TyCtxt, Instance}; use rustc::mir::mono::{MonoItem, InstantiationMode}; -use syntax_pos::symbol::InternedString; +use syntax_pos::symbol::Symbol; use log::debug; @@ -112,7 +112,7 @@ pub fn provide(providers: &mut Providers<'_>) { }; } -fn symbol_name(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> InternedString { +fn symbol_name(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Symbol { let def_id = instance.def_id(); let substs = instance.substs; @@ -123,13 +123,11 @@ fn symbol_name(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> InternedString { if def_id.is_local() { if tcx.plugin_registrar_fn(LOCAL_CRATE) == Some(def_id) { let disambiguator = tcx.sess.local_crate_disambiguator(); - return - InternedString::intern(&tcx.sess.generate_plugin_registrar_symbol(disambiguator)); + return Symbol::intern(&tcx.sess.generate_plugin_registrar_symbol(disambiguator)); } if tcx.proc_macro_decls_static(LOCAL_CRATE) == Some(def_id) { let disambiguator = tcx.sess.local_crate_disambiguator(); - return - InternedString::intern(&tcx.sess.generate_proc_macro_decls_symbol(disambiguator)); + return Symbol::intern(&tcx.sess.generate_proc_macro_decls_symbol(disambiguator)); } } @@ -146,23 +144,22 @@ fn symbol_name(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> InternedString { let attrs = tcx.codegen_fn_attrs(def_id); if is_foreign { if let Some(name) = attrs.link_name { - return name.as_interned_str(); + return name; } // Don't mangle foreign items. - return tcx.item_name(def_id).as_interned_str(); + return tcx.item_name(def_id); } - if let Some(name) = &attrs.export_name { + if let Some(name) = attrs.export_name { // Use provided name - return name.as_interned_str(); + return name; } if attrs.flags.contains(CodegenFnAttrFlags::NO_MANGLE) { // Don't mangle - return tcx.item_name(def_id).as_interned_str(); + return tcx.item_name(def_id); } - let is_generic = substs.non_erasable_generics().next().is_some(); let avoid_cross_crate_conflicts = // If this is an instance of a generic function, we also hash in @@ -222,5 +219,5 @@ fn symbol_name(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> InternedString { SymbolManglingVersion::V0 => v0::mangle(tcx, instance, instantiating_crate), }; - InternedString::intern(&mangled) + Symbol::intern(&mangled) } diff --git a/src/librustc_codegen_utils/symbol_names/legacy.rs b/src/librustc_codegen_utils/symbol_names/legacy.rs index cf575c54293c..601a33a66bb3 100644 --- a/src/librustc_codegen_utils/symbol_names/legacy.rs +++ b/src/librustc_codegen_utils/symbol_names/legacy.rs @@ -335,7 +335,7 @@ impl Printer<'tcx> for SymbolPrinter<'tcx> { self.path.finalize_pending_component(); } - self.write_str(&disambiguated_data.data.as_interned_str().as_str())?; + self.write_str(&disambiguated_data.data.as_symbol().as_str())?; Ok(self) } fn path_generic_args( diff --git a/src/librustc_data_structures/graph/dominators/mod.rs b/src/librustc_data_structures/graph/dominators/mod.rs index 29a8a98d229c..444463c08e55 100644 --- a/src/librustc_data_structures/graph/dominators/mod.rs +++ b/src/librustc_data_structures/graph/dominators/mod.rs @@ -17,7 +17,7 @@ pub fn dominators(graph: &G) -> Dominators { dominators_given_rpo(graph, &rpo) } -pub fn dominators_given_rpo( +fn dominators_given_rpo( graph: &G, rpo: &[G::Node], ) -> Dominators { @@ -43,14 +43,12 @@ pub fn dominators_given_rpo( let mut new_idom = None; for pred in graph.predecessors(node) { if immediate_dominators[pred].is_some() { - // (*) // (*) dominators for `pred` have been calculated - new_idom = intersect_opt( - &post_order_rank, - &immediate_dominators, - new_idom, - Some(pred), - ); + new_idom = Some(if let Some(new_idom) = new_idom { + intersect(&post_order_rank, &immediate_dominators, new_idom, pred) + } else { + pred + }); } } @@ -67,19 +65,6 @@ pub fn dominators_given_rpo( } } -fn intersect_opt( - post_order_rank: &IndexVec, - immediate_dominators: &IndexVec>, - node1: Option, - node2: Option, -) -> Option { - match (node1, node2) { - (None, None) => None, - (Some(n), None) | (None, Some(n)) => Some(n), - (Some(n1), Some(n2)) => Some(intersect(post_order_rank, immediate_dominators, n1, n2)), - } -} - fn intersect( post_order_rank: &IndexVec, immediate_dominators: &IndexVec>, diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml index aa74966d0ab4..a9e4e6db1c75 100644 --- a/src/librustc_driver/Cargo.toml +++ b/src/librustc_driver/Cargo.toml @@ -16,6 +16,7 @@ log = "0.4" env_logger = { version = "0.7", default-features = false } rustc = { path = "../librustc" } rustc_target = { path = "../librustc_target" } +rustc_lint = { path = "../librustc_lint" } rustc_data_structures = { path = "../librustc_data_structures" } errors = { path = "../librustc_errors", package = "rustc_errors" } rustc_metadata = { path = "../librustc_metadata" } diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index bfcbec8b78f3..15adf7e4add7 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -36,11 +36,11 @@ use rustc::session::config::nightly_options; use rustc::session::{early_error, early_warn}; use rustc::lint::Lint; use rustc::lint; +use rustc::middle::cstore::MetadataLoader; use rustc::hir::def_id::LOCAL_CRATE; use rustc::ty::TyCtxt; use rustc::util::common::{set_time_depth, time, print_time_passes_entry, ErrorReported}; use rustc_metadata::locator; -use rustc_metadata::cstore::CStore; use rustc_codegen_utils::codegen_backend::CodegenBackend; use rustc_interface::interface; use rustc_interface::util::get_codegen_sysroot; @@ -106,6 +106,8 @@ pub fn abort_on_err(result: Result, sess: &Session) -> T { pub trait Callbacks { /// Called before creating the compiler instance fn config(&mut self, _config: &mut interface::Config) {} + /// Called early during compilation to allow other drivers to easily register lints. + fn extra_lints(&mut self, _ls: &mut lint::LintStore) {} /// Called after parsing. Return value instructs the compiler whether to /// continue the compilation afterwards (defaults to `Compilation::Continue`) fn after_parsing(&mut self, _compiler: &interface::Compiler) -> Compilation { @@ -182,6 +184,7 @@ pub fn run_compiler( stderr: None, crate_name: None, lint_caps: Default::default(), + register_lints: None, }; callbacks.config(&mut config); config @@ -202,9 +205,13 @@ pub fn run_compiler( interface::run_compiler(config, |compiler| { let sopts = &compiler.session().opts; if sopts.describe_lints { + let lint_store = rustc_lint::new_lint_store( + sopts.debugging_opts.no_interleave_lints, + compiler.session().unstable_options(), + ); describe_lints( compiler.session(), - &*compiler.session().lint_store.borrow(), + &lint_store, false ); return; @@ -255,6 +262,7 @@ pub fn run_compiler( stderr: None, crate_name: None, lint_caps: Default::default(), + register_lints: None, }; callbacks.config(&mut config); @@ -269,7 +277,7 @@ pub fn run_compiler( compiler.output_file(), ).and_then(|| RustcDefaultCalls::list_metadata( sess, - compiler.cstore(), + &*compiler.codegen_backend().metadata_loader(), &matches, compiler.input() )); @@ -321,12 +329,14 @@ pub fn run_compiler( return sess.compile_status(); } - compiler.register_plugins()?; + { + let (_, _, lint_store) = &*compiler.register_plugins()?.peek(); - // Lint plugins are registered; now we can process command line flags. - if sess.opts.describe_lints { - describe_lints(&sess, &sess.lint_store.borrow(), true); - return sess.compile_status(); + // Lint plugins are registered; now we can process command line flags. + if sess.opts.describe_lints { + describe_lints(&sess, &lint_store, true); + return sess.compile_status(); + } } compiler.expansion()?; @@ -604,7 +614,7 @@ fn show_content_with_pager(content: &String) { impl RustcDefaultCalls { pub fn list_metadata(sess: &Session, - cstore: &CStore, + metadata_loader: &dyn MetadataLoader, matches: &getopts::Matches, input: &Input) -> Compilation { @@ -616,7 +626,7 @@ impl RustcDefaultCalls { let mut v = Vec::new(); locator::list_file_metadata(&sess.target.target, path, - cstore, + metadata_loader, &mut v) .unwrap(); println!("{}", String::from_utf8(v).unwrap()); @@ -835,8 +845,7 @@ Available lint options: "); - fn sort_lints(sess: &Session, lints: Vec<(&'static Lint, bool)>) -> Vec<&'static Lint> { - let mut lints: Vec<_> = lints.into_iter().map(|(x, _)| x).collect(); + fn sort_lints(sess: &Session, mut lints: Vec<&'static Lint>) -> Vec<&'static Lint> { // The sort doesn't case-fold but it's doubtful we care. lints.sort_by_cached_key(|x: &&Lint| (x.default_level(sess), x.name)); lints @@ -852,7 +861,7 @@ Available lint options: let (plugin, builtin): (Vec<_>, _) = lint_store.get_lints() .iter() .cloned() - .partition(|&(_, p)| p); + .partition(|&lint| lint.is_plugin); let plugin = sort_lints(sess, plugin); let builtin = sort_lints(sess, builtin); diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs index fd74d8673da4..1781f2e16503 100644 --- a/src/librustc_errors/diagnostic.rs +++ b/src/librustc_errors/diagnostic.rs @@ -152,6 +152,32 @@ impl Diagnostic { self.note_expected_found_extra(label, expected, found, &"", &"") } + pub fn note_unsuccessfull_coercion(&mut self, + expected: DiagnosticStyledString, + found: DiagnosticStyledString) + -> &mut Self + { + let mut msg: Vec<_> = + vec![(format!("required when trying to coerce from type `"), + Style::NoStyle)]; + msg.extend(expected.0.iter() + .map(|x| match *x { + StringPart::Normal(ref s) => (s.to_owned(), Style::NoStyle), + StringPart::Highlighted(ref s) => (s.to_owned(), Style::Highlight), + })); + msg.push((format!("` to type '"), Style::NoStyle)); + msg.extend(found.0.iter() + .map(|x| match *x { + StringPart::Normal(ref s) => (s.to_owned(), Style::NoStyle), + StringPart::Highlighted(ref s) => (s.to_owned(), Style::Highlight), + })); + msg.push((format!("`"), Style::NoStyle)); + + // For now, just attach these as notes + self.highlighted_note(msg); + self + } + pub fn note_expected_found_extra(&mut self, label: &dyn fmt::Display, expected: DiagnosticStyledString, diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs index cc60bf89c7ec..40642dd14b8f 100644 --- a/src/librustc_errors/diagnostic_builder.rs +++ b/src/librustc_errors/diagnostic_builder.rs @@ -209,6 +209,11 @@ impl<'a> DiagnosticBuilder<'a> { found_extra: &dyn fmt::Display, ) -> &mut Self); + forward!(pub fn note_unsuccessfull_coercion(&mut self, + expected: DiagnosticStyledString, + found: DiagnosticStyledString, + ) -> &mut Self); + forward!(pub fn note(&mut self, msg: &str) -> &mut Self); forward!(pub fn span_note>(&mut self, sp: S, diff --git a/src/librustc_incremental/assert_module_sources.rs b/src/librustc_incremental/assert_module_sources.rs index e08eeaf85758..ca035d0cdcb1 100644 --- a/src/librustc_incremental/assert_module_sources.rs +++ b/src/librustc_incremental/assert_module_sources.rs @@ -27,7 +27,7 @@ use rustc::mir::mono::CodegenUnitNameBuilder; use rustc::ty::TyCtxt; use std::collections::BTreeSet; use syntax::ast; -use syntax::symbol::{InternedString, Symbol, sym}; +use syntax::symbol::{Symbol, sym}; use rustc::ich::{ATTR_PARTITION_REUSED, ATTR_PARTITION_CODEGENED, ATTR_EXPECTED_CGU_REUSE}; @@ -45,8 +45,8 @@ pub fn assert_module_sources(tcx: TyCtxt<'_>) { .collect_and_partition_mono_items(LOCAL_CRATE) .1 .iter() - .map(|cgu| *cgu.name()) - .collect::>(); + .map(|cgu| cgu.name()) + .collect::>(); let ams = AssertModuleSource { tcx, @@ -61,7 +61,7 @@ pub fn assert_module_sources(tcx: TyCtxt<'_>) { struct AssertModuleSource<'tcx> { tcx: TyCtxt<'tcx>, - available_cgus: BTreeSet, + available_cgus: BTreeSet, } impl AssertModuleSource<'tcx> { diff --git a/src/librustc_interface/interface.rs b/src/librustc_interface/interface.rs index 5e1ad3e61dd1..e014e4ed0fdc 100644 --- a/src/librustc_interface/interface.rs +++ b/src/librustc_interface/interface.rs @@ -11,7 +11,6 @@ use rustc_codegen_utils::codegen_backend::CodegenBackend; use rustc_data_structures::OnDrop; use rustc_data_structures::sync::Lrc; use rustc_data_structures::fx::{FxHashSet, FxHashMap}; -use rustc_metadata::cstore::CStore; use std::path::PathBuf; use std::result; use std::sync::{Arc, Mutex}; @@ -37,8 +36,8 @@ pub struct Compiler { pub(crate) output_dir: Option, pub(crate) output_file: Option, pub(crate) queries: Queries, - pub(crate) cstore: Lrc, pub(crate) crate_name: Option, + pub(crate) register_lints: Option>, } impl Compiler { @@ -48,9 +47,6 @@ impl Compiler { pub fn codegen_backend(&self) -> &Lrc> { &self.codegen_backend } - pub fn cstore(&self) -> &Lrc { - &self.cstore - } pub fn source_map(&self) -> &Lrc { &self.source_map } @@ -137,6 +133,13 @@ pub struct Config { pub crate_name: Option, pub lint_caps: FxHashMap, + + /// This is a callback from the driver that is called when we're registering lints; + /// it is called during plugin registration when we have the LintStore in a non-shared state. + /// + /// Note that if you find a Some here you probably want to call that function in the new + /// function being registered. + pub register_lints: Option>, } pub fn run_compiler_in_existing_thread_pool(config: Config, f: F) -> R @@ -152,19 +155,17 @@ where config.lint_caps, ); - let cstore = Lrc::new(CStore::new(codegen_backend.metadata_loader())); - let compiler = Compiler { sess, codegen_backend, source_map, - cstore, input: config.input, input_path: config.input_path, output_dir: config.output_dir, output_file: config.output_file, queries: Default::default(), crate_name: config.crate_name, + register_lints: config.register_lints, }; let _sess_abort_error = OnDrop(|| { diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 89de5714695d..58936172c5bc 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -9,8 +9,8 @@ use rustc::hir::lowering::lower_crate; use rustc::hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc::lint; use rustc::middle::{self, reachable, resolve_lifetime, stability}; -use rustc::middle::cstore::CrateStore; -use rustc::ty::{self, AllArenas, Resolutions, TyCtxt, GlobalCtxt}; +use rustc::middle::cstore::{CrateStore, MetadataLoader, MetadataLoaderDyn}; +use rustc::ty::{self, AllArenas, ResolverOutputs, TyCtxt, GlobalCtxt}; use rustc::ty::steal::Steal; use rustc::traits; use rustc::util::common::{time, ErrorReported}; @@ -23,8 +23,7 @@ use rustc_codegen_utils::link::filename_for_metadata; use rustc_data_structures::{box_region_allow_access, declare_box_region_type, parallel}; use rustc_data_structures::sync::{Lrc, ParallelIterator, par_iter}; use rustc_incremental; -use rustc_metadata::creader::CrateLoader; -use rustc_metadata::cstore::{self, CStore}; +use rustc_metadata::cstore; use rustc_mir as mir; use rustc_passes::{self, ast_validation, hir_stats, layout_test}; use rustc_plugin as plugin; @@ -46,12 +45,10 @@ use syntax_ext; use rustc_serialize::json; use tempfile::Builder as TempFileBuilder; +use std::{env, fs, iter, mem}; use std::any::Any; -use std::env; use std::ffi::OsString; -use std::fs; use std::io::{self, Write}; -use std::iter; use std::path::PathBuf; use std::cell::RefCell; use std::rc::Rc; @@ -105,7 +102,7 @@ fn count_nodes(krate: &ast::Crate) -> usize { declare_box_region_type!( pub BoxedResolver, for(), - (&mut Resolver<'_>) -> (Result, ExpansionResult) + (&mut Resolver<'_>) -> (Result, ResolverOutputs) ); /// Runs the "early phases" of the compiler: initial `cfg` processing, @@ -117,7 +114,8 @@ declare_box_region_type!( /// Returns `None` if we're aborting after handling -W help. pub fn configure_and_expand( sess: Lrc, - cstore: Lrc, + lint_store: Lrc, + metadata_loader: Box, krate: ast::Crate, crate_name: &str, plugin_info: PluginInfo, @@ -130,15 +128,14 @@ pub fn configure_and_expand( let crate_name = crate_name.to_string(); let (result, resolver) = BoxedResolver::new(static move || { let sess = &*sess; - let crate_loader = CrateLoader::new(sess, &*cstore, &crate_name); let resolver_arenas = Resolver::arenas(); let res = configure_and_expand_inner( sess, - &*cstore, + &lint_store, krate, &crate_name, &resolver_arenas, - &crate_loader, + &*metadata_loader, plugin_info, ); let mut resolver = match res { @@ -152,68 +149,16 @@ pub fn configure_and_expand( } }; box_region_allow_access!(for(), (&mut Resolver<'_>), (&mut resolver)); - ExpansionResult::from_owned_resolver(resolver) + resolver.into_outputs() }); result.map(|k| (k, resolver)) } -pub struct ExpansionResult { - pub defs: Steal, - pub resolutions: Steal, -} - -impl ExpansionResult { - fn from_owned_resolver( - resolver: Resolver<'_>, - ) -> Self { - ExpansionResult { - defs: Steal::new(resolver.definitions), - resolutions: Steal::new(Resolutions { - extern_crate_map: resolver.extern_crate_map, - export_map: resolver.export_map, - trait_map: resolver.trait_map, - glob_map: resolver.glob_map, - maybe_unused_trait_imports: resolver.maybe_unused_trait_imports, - maybe_unused_extern_crates: resolver.maybe_unused_extern_crates, - extern_prelude: resolver.extern_prelude.iter().map(|(ident, entry)| { - (ident.name, entry.introduced_by_item) - }).collect(), - }), - } - } - - pub fn from_resolver_ref( - resolver: &Resolver<'_>, - ) -> Self { - ExpansionResult { - defs: Steal::new(resolver.definitions.clone()), - resolutions: Steal::new(Resolutions { - extern_crate_map: resolver.extern_crate_map.clone(), - export_map: resolver.export_map.clone(), - trait_map: resolver.trait_map.clone(), - glob_map: resolver.glob_map.clone(), - maybe_unused_trait_imports: resolver.maybe_unused_trait_imports.clone(), - maybe_unused_extern_crates: resolver.maybe_unused_extern_crates.clone(), - extern_prelude: resolver.extern_prelude.iter().map(|(ident, entry)| { - (ident.name, entry.introduced_by_item) - }).collect(), - }), - } - } -} - impl BoxedResolver { - pub fn to_expansion_result( - resolver: Rc>, - ) -> ExpansionResult { + pub fn to_resolver_outputs(resolver: Rc>) -> ResolverOutputs { match Rc::try_unwrap(resolver) { Ok(resolver) => resolver.into_inner().complete(), - Err(resolver) => { - let resolver = &*resolver; - resolver.borrow_mut().access(|resolver| { - ExpansionResult::from_resolver_ref(resolver) - }) - } + Err(resolver) => resolver.borrow_mut().access(|resolver| resolver.clone_outputs()), } } } @@ -224,10 +169,11 @@ pub struct PluginInfo { pub fn register_plugins<'a>( sess: &'a Session, - cstore: &'a CStore, + metadata_loader: &'a dyn MetadataLoader, + register_lints: impl Fn(&Session, &mut lint::LintStore), mut krate: ast::Crate, crate_name: &str, -) -> Result<(ast::Crate, PluginInfo)> { +) -> Result<(ast::Crate, PluginInfo, Lrc)> { krate = time(sess, "attributes injection", || { syntax_ext::cmdline_attrs::inject( krate, &sess.parse_sess, &sess.opts.debugging_opts.crate_attr @@ -271,14 +217,20 @@ pub fn register_plugins<'a>( let registrars = time(sess, "plugin loading", || { plugin::load::load_plugins( sess, - &cstore, + metadata_loader, &krate, - crate_name, Some(sess.opts.debugging_opts.extra_plugins.clone()), ) }); - let mut registry = Registry::new(sess, krate.span); + let mut lint_store = rustc_lint::new_lint_store( + sess.opts.debugging_opts.no_interleave_lints, + sess.unstable_options(), + ); + + (register_lints)(&sess, &mut lint_store); + + let mut registry = Registry::new(sess, &mut lint_store, krate.span); time(sess, "plugin registration", || { for registrar in registrars { @@ -289,44 +241,30 @@ pub fn register_plugins<'a>( let Registry { syntax_exts, - early_lint_passes, - late_lint_passes, - lint_groups, llvm_passes, attributes, .. } = registry; - let mut ls = sess.lint_store.borrow_mut(); - for pass in early_lint_passes { - ls.register_early_pass(Some(sess), true, false, pass); - } - for pass in late_lint_passes { - ls.register_late_pass(Some(sess), true, false, false, pass); - } - - for (name, (to, deprecated_name)) in lint_groups { - ls.register_group(Some(sess), true, name, deprecated_name, to); - } - *sess.plugin_llvm_passes.borrow_mut() = llvm_passes; *sess.plugin_attributes.borrow_mut() = attributes; - Ok((krate, PluginInfo { syntax_exts })) + Ok((krate, PluginInfo { syntax_exts }, Lrc::new(lint_store))) } fn configure_and_expand_inner<'a>( sess: &'a Session, - cstore: &'a CStore, + lint_store: &'a lint::LintStore, mut krate: ast::Crate, crate_name: &str, resolver_arenas: &'a ResolverArenas<'a>, - crate_loader: &'a CrateLoader<'a>, + metadata_loader: &'a MetadataLoaderDyn, plugin_info: PluginInfo, ) -> Result<(ast::Crate, Resolver<'a>)> { time(sess, "pre-AST-expansion lint checks", || { lint::check_ast_crate( sess, + lint_store, &krate, true, rustc_lint::BuiltinCombinedPreExpansionLintPass::new()); @@ -334,10 +272,9 @@ fn configure_and_expand_inner<'a>( let mut resolver = Resolver::new( sess, - cstore, &krate, crate_name, - crate_loader, + metadata_loader, &resolver_arenas, ); syntax_ext::register_builtin_macros(&mut resolver, sess.edition()); @@ -536,7 +473,7 @@ fn configure_and_expand_inner<'a>( pub fn lower_to_hir( sess: &Session, - cstore: &CStore, + lint_store: &lint::LintStore, resolver: &mut Resolver<'_>, dep_graph: &DepGraph, krate: &ast::Crate, @@ -544,7 +481,7 @@ pub fn lower_to_hir( // Lower AST to HIR. let hir_forest = time(sess, "lowering AST -> HIR", || { let nt_to_tokenstream = syntax::parse::nt_to_tokenstream; - let hir_crate = lower_crate(sess, cstore, &dep_graph, &krate, resolver, nt_to_tokenstream); + let hir_crate = lower_crate(sess, &dep_graph, &krate, resolver, nt_to_tokenstream); if sess.opts.debugging_opts.hir_stats { hir_stats::print_hir_stats(&hir_crate); @@ -554,7 +491,13 @@ pub fn lower_to_hir( }); time(sess, "early lint checks", || { - lint::check_ast_crate(sess, &krate, false, rustc_lint::BuiltinCombinedEarlyLintPass::new()) + lint::check_ast_crate( + sess, + lint_store, + &krate, + false, + rustc_lint::BuiltinCombinedEarlyLintPass::new(), + ) }); // Discard hygiene data, which isn't required after lowering to HIR. @@ -644,8 +587,12 @@ fn escape_dep_filename(filename: &FileName) -> String { filename.to_string().replace(" ", "\\ ") } -fn write_out_deps(compiler: &Compiler, outputs: &OutputFilenames, out_filenames: &[PathBuf]) { - let sess = &compiler.sess; +fn write_out_deps( + sess: &Session, + boxed_resolver: &Steal>>, + outputs: &OutputFilenames, + out_filenames: &[PathBuf], +) { // Write out dependency rules to the dep-info file if requested if !sess.opts.output_types.contains_key(&OutputType::DepInfo) { return; @@ -664,18 +611,20 @@ fn write_out_deps(compiler: &Compiler, outputs: &OutputFilenames, out_filenames: .collect(); if sess.binary_dep_depinfo() { - for cnum in compiler.cstore.crates_untracked() { - let source = compiler.cstore.crate_source_untracked(cnum); - if let Some((path, _)) = source.dylib { - files.push(escape_dep_filename(&FileName::Real(path))); + boxed_resolver.borrow().borrow_mut().access(|resolver| { + for cnum in resolver.cstore().crates_untracked() { + let source = resolver.cstore().crate_source_untracked(cnum); + if let Some((path, _)) = source.dylib { + files.push(escape_dep_filename(&FileName::Real(path))); + } + if let Some((path, _)) = source.rlib { + files.push(escape_dep_filename(&FileName::Real(path))); + } + if let Some((path, _)) = source.rmeta { + files.push(escape_dep_filename(&FileName::Real(path))); + } } - if let Some((path, _)) = source.rlib { - files.push(escape_dep_filename(&FileName::Real(path))); - } - if let Some((path, _)) = source.rmeta { - files.push(escape_dep_filename(&FileName::Real(path))); - } - } + }); } let mut file = fs::File::create(&deps_filename)?; @@ -713,6 +662,7 @@ pub fn prepare_outputs( sess: &Session, compiler: &Compiler, krate: &ast::Crate, + boxed_resolver: &Steal>>, crate_name: &str ) -> Result { // FIXME: rustdoc passes &[] instead of &krate.attrs here @@ -754,7 +704,7 @@ pub fn prepare_outputs( } } - write_out_deps(compiler, &outputs, &output_paths); + write_out_deps(sess, boxed_resolver, &outputs, &output_paths); let only_dep_info = sess.opts.output_types.contains_key(&OutputType::DepInfo) && sess.opts.output_types.len() == 1; @@ -817,27 +767,26 @@ impl BoxedGlobalCtxt { pub fn create_global_ctxt( compiler: &Compiler, + lint_store: Lrc, mut hir_forest: hir::map::Forest, - defs: hir::map::Definitions, - resolutions: Resolutions, + mut resolver_outputs: ResolverOutputs, outputs: OutputFilenames, crate_name: &str, ) -> BoxedGlobalCtxt { let sess = compiler.session().clone(); - let cstore = compiler.cstore.clone(); let codegen_backend = compiler.codegen_backend().clone(); let crate_name = crate_name.to_string(); + let defs = mem::take(&mut resolver_outputs.definitions); let ((), result) = BoxedGlobalCtxt::new(static move || { let sess = &*sess; - let cstore = &*cstore; let global_ctxt: Option>; let arenas = AllArenas::new(); // Construct the HIR map. let hir_map = time(sess, "indexing HIR", || { - hir::map::map_crate(sess, cstore, &mut hir_forest, &defs) + hir::map::map_crate(sess, &*resolver_outputs.cstore, &mut hir_forest, &defs) }); let query_result_on_disk_cache = time(sess, "load query result cache", || { @@ -854,11 +803,11 @@ pub fn create_global_ctxt( let gcx = TyCtxt::create_global_ctxt( sess, - cstore, + lint_store, local_providers, extern_providers, &arenas, - resolutions, + resolver_outputs, hir_map, query_result_on_disk_cache, &crate_name, diff --git a/src/librustc_interface/queries.rs b/src/librustc_interface/queries.rs index cd72dc9453c7..ea51e63725ea 100644 --- a/src/librustc_interface/queries.rs +++ b/src/librustc_interface/queries.rs @@ -1,12 +1,17 @@ use crate::interface::{Compiler, Result}; -use crate::passes::{self, BoxedResolver, ExpansionResult, BoxedGlobalCtxt, PluginInfo}; +use crate::passes::{self, BoxedResolver, BoxedGlobalCtxt, PluginInfo}; use rustc_incremental::DepGraphFuture; +use rustc_data_structures::sync::Lrc; use rustc::session::config::{OutputFilenames, OutputType}; use rustc::util::common::{time, ErrorReported}; use rustc::hir; +use rustc::lint; +use rustc::session::Session; +use rustc::lint::LintStore; use rustc::hir::def_id::LOCAL_CRATE; use rustc::ty::steal::Steal; +use rustc::ty::ResolverOutputs; use rustc::dep_graph::DepGraph; use std::cell::{Ref, RefMut, RefCell}; use std::rc::Rc; @@ -74,10 +79,10 @@ pub(crate) struct Queries { dep_graph_future: Query>, parse: Query, crate_name: Query, - register_plugins: Query<(ast::Crate, PluginInfo)>, - expansion: Query<(ast::Crate, Steal>>)>, + register_plugins: Query<(ast::Crate, PluginInfo, Lrc)>, + expansion: Query<(ast::Crate, Steal>>, Lrc)>, dep_graph: Query, - lower_to_hir: Query<(Steal, ExpansionResult)>, + lower_to_hir: Query<(Steal, Steal)>, prepare_outputs: Query, global_ctxt: Query, ongoing_codegen: Query>, @@ -106,14 +111,19 @@ impl Compiler { }) } - pub fn register_plugins(&self) -> Result<&Query<(ast::Crate, PluginInfo)>> { + pub fn register_plugins(&self) -> Result<&Query<(ast::Crate, PluginInfo, Lrc)>> { self.queries.register_plugins.compute(|| { let crate_name = self.crate_name()?.peek().clone(); let krate = self.parse()?.take(); + let empty: &(dyn Fn(&Session, &mut lint::LintStore) + Sync + Send) = &|_, _| {}; let result = passes::register_plugins( self.session(), - self.cstore(), + &*self.codegen_backend().metadata_loader(), + self.register_lints + .as_ref() + .map(|p| &**p) + .unwrap_or_else(|| empty), krate, &crate_name, ); @@ -148,17 +158,20 @@ impl Compiler { pub fn expansion( &self - ) -> Result<&Query<(ast::Crate, Steal>>)>> { + ) -> Result<&Query<(ast::Crate, Steal>>, Lrc)>> { self.queries.expansion.compute(|| { let crate_name = self.crate_name()?.peek().clone(); - let (krate, plugin_info) = self.register_plugins()?.take(); + let (krate, plugin_info, lint_store) = self.register_plugins()?.take(); passes::configure_and_expand( self.sess.clone(), - self.cstore().clone(), + lint_store.clone(), + self.codegen_backend().metadata_loader(), krate, &crate_name, plugin_info, - ).map(|(krate, resolver)| (krate, Steal::new(Rc::new(RefCell::new(resolver))))) + ).map(|(krate, resolver)| { + (krate, Steal::new(Rc::new(RefCell::new(resolver))), lint_store) + }) }) } @@ -179,32 +192,35 @@ impl Compiler { }) } - pub fn lower_to_hir(&self) -> Result<&Query<(Steal, ExpansionResult)>> { + pub fn lower_to_hir( + &self, + ) -> Result<&Query<(Steal, Steal)>> { self.queries.lower_to_hir.compute(|| { let expansion_result = self.expansion()?; let peeked = expansion_result.peek(); let krate = &peeked.0; let resolver = peeked.1.steal(); + let lint_store = &peeked.2; let hir = Steal::new(resolver.borrow_mut().access(|resolver| { passes::lower_to_hir( self.session(), - self.cstore(), + lint_store, resolver, &*self.dep_graph()?.peek(), &krate ) })?); - Ok((hir, BoxedResolver::to_expansion_result(resolver))) + Ok((hir, Steal::new(BoxedResolver::to_resolver_outputs(resolver)))) }) } pub fn prepare_outputs(&self) -> Result<&Query> { self.queries.prepare_outputs.compute(|| { - let krate = self.expansion()?; - let krate = krate.peek(); + let expansion_result = self.expansion()?; + let (krate, boxed_resolver, _) = &*expansion_result.peek(); let crate_name = self.crate_name()?; let crate_name = crate_name.peek(); - passes::prepare_outputs(self.session(), self, &krate.0, &*crate_name) + passes::prepare_outputs(self.session(), self, &krate, &boxed_resolver, &crate_name) }) } @@ -212,14 +228,15 @@ impl Compiler { self.queries.global_ctxt.compute(|| { let crate_name = self.crate_name()?.peek().clone(); let outputs = self.prepare_outputs()?.peek().clone(); + let lint_store = self.expansion()?.peek().2.clone(); let hir = self.lower_to_hir()?; let hir = hir.peek(); - let (ref hir_forest, ref expansion) = *hir; + let (hir_forest, resolver_outputs) = &*hir; Ok(passes::create_global_ctxt( self, + lint_store, hir_forest.steal(), - expansion.defs.steal(), - expansion.resolutions.steal(), + resolver_outputs.steal(), outputs, &crate_name)) }) diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs index 0c272f0c4563..8f11dc937272 100644 --- a/src/librustc_interface/util.rs +++ b/src/librustc_interface/util.rs @@ -13,7 +13,6 @@ use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::thin_vec::ThinVec; use rustc_data_structures::fx::{FxHashSet, FxHashMap}; use rustc_errors::registry::Registry; -use rustc_lint; use rustc_metadata::dynamic_lib::DynamicLibrary; use rustc_mir; use rustc_passes; @@ -108,11 +107,6 @@ pub fn create_session( let codegen_backend = get_codegen_backend(&sess); - rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); - if sess.unstable_options() { - rustc_lint::register_internals(&mut sess.lint_store.borrow_mut(), Some(&sess)); - } - let mut cfg = config::build_configuration(&sess, config::to_crate_config(cfg)); add_configuration(&mut cfg, &sess, &*codegen_backend); sess.parse_sess.config = cfg; diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 5d9a97cc21ee..ad674911e6f3 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -27,6 +27,7 @@ use rustc::hir::def::{Res, DefKind}; use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::ty::{self, Ty, TyCtxt, layout::VariantIdx}; use rustc::{lint, util}; +use rustc::lint::FutureIncompatibleInfo; use hir::Node; use util::nodemap::HirIdSet; use lint::{LateContext, LintContext, LintArray}; @@ -280,7 +281,7 @@ declare_lint! { pub MISSING_DOCS, Allow, "detects missing documentation for public members", - report_in_external_macro: true + report_in_external_macro } pub struct MissingDoc { @@ -601,7 +602,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDebugImplementations { declare_lint! { pub ANONYMOUS_PARAMETERS, Allow, - "detects anonymous parameters" + "detects anonymous parameters", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #41686 ", + edition: Some(Edition::Edition2018), + }; } declare_lint_pass!( @@ -1344,7 +1349,7 @@ declare_lint! { UNNAMEABLE_TEST_ITEMS, Warn, "detects an item that cannot be named being marked as `#[test_case]`", - report_in_external_macro: true + report_in_external_macro } pub struct UnnameableTestItems { @@ -1393,7 +1398,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnameableTestItems { declare_lint! { pub KEYWORD_IDENTS, Allow, - "detects edition keywords being used as an identifier" + "detects edition keywords being used as an identifier", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #49716 ", + edition: Some(Edition::Edition2018), + }; } declare_lint_pass!( diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index f83755181f82..b1beef04c592 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -33,27 +33,21 @@ use rustc::lint; use rustc::lint::{EarlyContext, LateContext, LateLintPass, EarlyLintPass, LintPass, LintArray}; use rustc::lint::builtin::{ BARE_TRAIT_OBJECTS, - ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE, ELIDED_LIFETIMES_IN_PATHS, EXPLICIT_OUTLIVES_REQUIREMENTS, INTRA_DOC_LINK_RESOLUTION_FAILURE, MISSING_DOC_CODE_EXAMPLES, PRIVATE_DOC_TESTS, - parser::ILL_FORMED_ATTRIBUTE_INPUT, }; -use rustc::session; use rustc::hir; use rustc::hir::def_id::DefId; use rustc::ty::query::Providers; use rustc::ty::TyCtxt; use syntax::ast; -use syntax::edition::Edition; use syntax_pos::Span; -use session::Session; use lint::LintId; -use lint::FutureIncompatibleInfo; use redundant_semicolon::*; use nonstandard_style::*; @@ -192,59 +186,60 @@ late_lint_passes!(declare_combined_late_pass, [pub BuiltinCombinedLateLintPass]) late_lint_mod_passes!(declare_combined_late_pass, [BuiltinCombinedModuleLateLintPass]); +pub fn new_lint_store(no_interleave_lints: bool, internal_lints: bool) -> lint::LintStore { + let mut lint_store = lint::LintStore::new(); + + register_builtins(&mut lint_store, no_interleave_lints); + if internal_lints { + register_internals(&mut lint_store); + } + + lint_store +} + /// Tell the `LintStore` about all the built-in lints (the ones /// defined in this crate and the ones defined in /// `rustc::lint::builtin`). -pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { +fn register_builtins(store: &mut lint::LintStore, no_interleave_lints: bool) { macro_rules! add_lint_group { - ($sess:ident, $name:expr, $($lint:ident),*) => ( - store.register_group($sess, false, $name, None, vec![$(LintId::of($lint)),*]); + ($name:expr, $($lint:ident),*) => ( + store.register_group(false, $name, None, vec![$(LintId::of($lint)),*]); ) } macro_rules! register_pass { - ($method:ident, $constructor:expr, [$($args:expr),*]) => ( - store.$method(sess, false, false, $($args,)* box $constructor); + ($method:ident, $ty:ident, $constructor:expr) => ( + store.register_lints(&$ty::get_lints()); + store.$method(|| box $constructor); ) } macro_rules! register_passes { - ([$method:ident, $args:tt], [$($passes:ident: $constructor:expr,)*]) => ( + ($method:ident, [$($passes:ident: $constructor:expr,)*]) => ( $( - register_pass!($method, $constructor, $args); + register_pass!($method, $passes, $constructor); )* ) } - if sess.map(|sess| sess.opts.debugging_opts.no_interleave_lints).unwrap_or(false) { - pre_expansion_lint_passes!(register_passes, [register_pre_expansion_pass, []]); - early_lint_passes!(register_passes, [register_early_pass, []]); - late_lint_passes!(register_passes, [register_late_pass, [false]]); - late_lint_mod_passes!(register_passes, [register_late_pass, [true]]); + if no_interleave_lints { + pre_expansion_lint_passes!(register_passes, register_pre_expansion_pass); + early_lint_passes!(register_passes, register_early_pass); + late_lint_passes!(register_passes, register_late_pass); + late_lint_mod_passes!(register_passes, register_late_mod_pass); } else { - store.register_pre_expansion_pass( - sess, - false, - true, - box BuiltinCombinedPreExpansionLintPass::new() - ); - store.register_early_pass(sess, false, true, box BuiltinCombinedEarlyLintPass::new()); - store.register_late_pass( - sess, false, true, true, box BuiltinCombinedModuleLateLintPass::new() - ); - store.register_late_pass( - sess, false, true, false, box BuiltinCombinedLateLintPass::new() - ); + store.register_lints(&BuiltinCombinedPreExpansionLintPass::get_lints()); + store.register_lints(&BuiltinCombinedEarlyLintPass::get_lints()); + store.register_lints(&BuiltinCombinedModuleLateLintPass::get_lints()); + store.register_lints(&BuiltinCombinedLateLintPass::get_lints()); } - add_lint_group!(sess, - "nonstandard_style", + add_lint_group!("nonstandard_style", NON_CAMEL_CASE_TYPES, NON_SNAKE_CASE, NON_UPPER_CASE_GLOBALS); - add_lint_group!(sess, - "unused", + add_lint_group!("unused", UNUSED_IMPORTS, UNUSED_VARIABLES, UNUSED_ASSIGNMENTS, @@ -265,8 +260,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { UNUSED_LABELS, UNUSED_PARENS); - add_lint_group!(sess, - "rust_2018_idioms", + add_lint_group!("rust_2018_idioms", BARE_TRAIT_OBJECTS, UNUSED_EXTERN_CRATES, ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, @@ -282,165 +276,11 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { // MACRO_USE_EXTERN_CRATE, ); - add_lint_group!(sess, - "rustdoc", + add_lint_group!("rustdoc", INTRA_DOC_LINK_RESOLUTION_FAILURE, MISSING_DOC_CODE_EXAMPLES, PRIVATE_DOC_TESTS); - // Guidelines for creating a future incompatibility lint: - // - // - Create a lint defaulting to warn as normal, with ideally the same error - // message you would normally give - // - Add a suitable reference, typically an RFC or tracking issue. Go ahead - // and include the full URL, sort items in ascending order of issue numbers. - // - Later, change lint to error - // - Eventually, remove lint - store.register_future_incompatible(sess, vec![ - FutureIncompatibleInfo { - id: LintId::of(PRIVATE_IN_PUBLIC), - reference: "issue #34537 ", - edition: None, - }, - FutureIncompatibleInfo { - id: LintId::of(PUB_USE_OF_PRIVATE_EXTERN_CRATE), - reference: "issue #34537 ", - edition: None, - }, - FutureIncompatibleInfo { - id: LintId::of(PATTERNS_IN_FNS_WITHOUT_BODY), - reference: "issue #35203 ", - edition: None, - }, - FutureIncompatibleInfo { - id: LintId::of(DUPLICATE_MACRO_EXPORTS), - reference: "issue #35896 ", - edition: Some(Edition::Edition2018), - }, - FutureIncompatibleInfo { - id: LintId::of(KEYWORD_IDENTS), - reference: "issue #49716 ", - edition: Some(Edition::Edition2018), - }, - FutureIncompatibleInfo { - id: LintId::of(SAFE_EXTERN_STATICS), - reference: "issue #36247 ", - edition: None, - }, - FutureIncompatibleInfo { - id: LintId::of(INVALID_TYPE_PARAM_DEFAULT), - reference: "issue #36887 ", - edition: None, - }, - FutureIncompatibleInfo { - id: LintId::of(LEGACY_DIRECTORY_OWNERSHIP), - reference: "issue #37872 ", - edition: None, - }, - FutureIncompatibleInfo { - id: LintId::of(LEGACY_CONSTRUCTOR_VISIBILITY), - reference: "issue #39207 ", - edition: None, - }, - FutureIncompatibleInfo { - id: LintId::of(MISSING_FRAGMENT_SPECIFIER), - reference: "issue #40107 ", - edition: None, - }, - FutureIncompatibleInfo { - id: LintId::of(ILLEGAL_FLOATING_POINT_LITERAL_PATTERN), - reference: "issue #41620 ", - edition: None, - }, - FutureIncompatibleInfo { - id: LintId::of(ANONYMOUS_PARAMETERS), - reference: "issue #41686 ", - edition: Some(Edition::Edition2018), - }, - FutureIncompatibleInfo { - id: LintId::of(PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES), - reference: "issue #42238 ", - edition: None, - }, - FutureIncompatibleInfo { - id: LintId::of(LATE_BOUND_LIFETIME_ARGUMENTS), - reference: "issue #42868 ", - edition: None, - }, - FutureIncompatibleInfo { - id: LintId::of(SAFE_PACKED_BORROWS), - reference: "issue #46043 ", - edition: None, - }, - FutureIncompatibleInfo { - id: LintId::of(ORDER_DEPENDENT_TRAIT_OBJECTS), - reference: "issue #56484 ", - edition: None, - }, - FutureIncompatibleInfo { - id: LintId::of(TYVAR_BEHIND_RAW_POINTER), - reference: "issue #46906 ", - edition: Some(Edition::Edition2018), - }, - FutureIncompatibleInfo { - id: LintId::of(UNSTABLE_NAME_COLLISIONS), - reference: "issue #48919 ", - edition: None, - // Note: this item represents future incompatibility of all unstable functions in the - // standard library, and thus should never be removed or changed to an error. - }, - FutureIncompatibleInfo { - id: LintId::of(ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE), - reference: "issue #53130 ", - edition: Some(Edition::Edition2018), - }, - FutureIncompatibleInfo { - id: LintId::of(WHERE_CLAUSES_OBJECT_SAFETY), - reference: "issue #51443 ", - edition: None, - }, - FutureIncompatibleInfo { - id: LintId::of(PROC_MACRO_DERIVE_RESOLUTION_FALLBACK), - reference: "issue #50504 ", - edition: None, - }, - FutureIncompatibleInfo { - id: LintId::of(MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS), - reference: "issue #52234 ", - edition: None, - }, - FutureIncompatibleInfo { - id: LintId::of(ILL_FORMED_ATTRIBUTE_INPUT), - reference: "issue #57571 ", - edition: None, - }, - FutureIncompatibleInfo { - id: LintId::of(AMBIGUOUS_ASSOCIATED_ITEMS), - reference: "issue #57644 ", - edition: None, - }, - FutureIncompatibleInfo { - id: LintId::of(NESTED_IMPL_TRAIT), - reference: "issue #59014 ", - edition: None, - }, - FutureIncompatibleInfo { - id: LintId::of(MUTABLE_BORROW_RESERVATION_CONFLICT), - reference: "issue #59159 ", - edition: None, - }, - FutureIncompatibleInfo { - id: LintId::of(INDIRECT_STRUCTURAL_MATCH), - reference: "issue #62411 ", - edition: None, - }, - FutureIncompatibleInfo { - id: LintId::of(SOFT_UNSTABLE), - reference: "issue #64266 ", - edition: None, - }, - ]); - // Register renamed and removed lints. store.register_renamed("single_use_lifetime", "single_use_lifetimes"); store.register_renamed("elided_lifetime_in_path", "elided_lifetimes_in_paths"); @@ -496,12 +336,14 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { "converted into hard error, see https://github.com/rust-lang/rust/issues/46205"); } -pub fn register_internals(store: &mut lint::LintStore, sess: Option<&Session>) { - store.register_early_pass(sess, false, false, box DefaultHashTypes::new()); - store.register_early_pass(sess, false, false, box LintPassImpl); - store.register_late_pass(sess, false, false, false, box TyTyKind); +fn register_internals(store: &mut lint::LintStore) { + store.register_lints(&DefaultHashTypes::get_lints()); + store.register_early_pass(|| box DefaultHashTypes::new()); + store.register_lints(&LintPassImpl::get_lints()); + store.register_early_pass(|| box LintPassImpl); + store.register_lints(&TyTyKind::get_lints()); + store.register_late_pass(|| box TyTyKind); store.register_group( - sess, false, "rustc::internal", None, diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index a93946df68f9..61b8cbe369aa 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -25,7 +25,7 @@ declare_lint! { pub UNUSED_MUST_USE, Warn, "unused result of a type flagged as `#[must_use]`", - report_in_external_macro: true + report_in_external_macro } declare_lint! { diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 7412e8a2cb9b..f0a68058de8c 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -3,7 +3,7 @@ use crate::cstore::{self, CStore, MetadataBlob}; use crate::locator::{self, CratePaths}; use crate::schema::{CrateRoot, CrateDep}; -use rustc_data_structures::sync::{Lrc, RwLock, Lock, AtomicCell}; +use rustc_data_structures::sync::{RwLock, Lock, AtomicCell}; use rustc::hir::def_id::CrateNum; use rustc_data_structures::svh::Svh; @@ -14,21 +14,20 @@ use rustc::session::{Session, CrateDisambiguator}; use rustc::session::config::{Sanitizer, self}; use rustc_target::spec::{PanicStrategy, TargetTriple}; use rustc::session::search_paths::PathKind; -use rustc::middle::cstore::{CrateSource, ExternCrate, ExternCrateSource}; +use rustc::middle::cstore::{CrateSource, ExternCrate, ExternCrateSource, MetadataLoaderDyn}; use rustc::util::common::record_time; use rustc::util::nodemap::FxHashSet; use rustc::hir::map::Definitions; use rustc::hir::def_id::LOCAL_CRATE; -use std::ops::Deref; -use std::path::{Path, PathBuf}; +use std::path::Path; use std::{cmp, fs}; use syntax::ast; use syntax::attr; use syntax_expand::allocator::{global_allocator_spans, AllocatorKind}; use syntax::symbol::{Symbol, sym}; -use syntax::{span_err, span_fatal}; +use syntax::span_fatal; use syntax_pos::{Span, DUMMY_SP}; use log::{debug, info, log_enabled}; use proc_macro::bridge::client::ProcMacro; @@ -39,9 +38,12 @@ crate struct Library { } pub struct CrateLoader<'a> { + // Immutable configuration. sess: &'a Session, - cstore: &'a CStore, + metadata_loader: &'a MetadataLoaderDyn, local_crate_name: Symbol, + // Mutable output. + cstore: CStore, } fn dump_crates(cstore: &CStore) { @@ -58,29 +60,6 @@ fn dump_crates(cstore: &CStore) { }); } -// Extra info about a crate loaded for plugins or exported macros. -struct ExtensionCrate { - metadata: PMDSource, - dylib: Option, - target_only: bool, -} - -enum PMDSource { - Registered(Lrc), - Owned(Library), -} - -impl Deref for PMDSource { - type Target = MetadataBlob; - - fn deref(&self) -> &MetadataBlob { - match *self { - PMDSource::Registered(ref cmd) => &cmd.blob, - PMDSource::Owned(ref lib) => &lib.metadata - } - } -} - enum LoadResult { Previous(CrateNum), Loaded(Library), @@ -99,14 +78,27 @@ impl<'a> LoadError<'a> { } impl<'a> CrateLoader<'a> { - pub fn new(sess: &'a Session, cstore: &'a CStore, local_crate_name: &str) -> Self { + pub fn new( + sess: &'a Session, + metadata_loader: &'a MetadataLoaderDyn, + local_crate_name: &str, + ) -> Self { CrateLoader { sess, - cstore, + metadata_loader, local_crate_name: Symbol::intern(local_crate_name), + cstore: Default::default(), } } + pub fn cstore(&self) -> &CStore { + &self.cstore + } + + pub fn into_cstore(self) -> CStore { + self.cstore + } + fn existing_match(&self, name: Symbol, hash: Option<&Svh>, kind: PathKind) -> Option { let mut ret = None; @@ -187,14 +179,14 @@ impl<'a> CrateLoader<'a> { } fn register_crate( - &self, + &mut self, host_lib: Option, root: Option<&CratePaths>, span: Span, lib: Library, dep_kind: DepKind, name: Symbol - ) -> (CrateNum, Lrc) { + ) -> CrateNum { let _prof_timer = self.sess.prof.generic_activity("metadata_register_crate"); let Library { source, metadata } = lib; @@ -248,9 +240,9 @@ impl<'a> CrateLoader<'a> { crate_root.def_path_table.decode((&metadata, self.sess)) }); - let cmeta = cstore::CrateMetadata { + self.cstore.set_crate_data(cnum, cstore::CrateMetadata { extern_crate: Lock::new(None), - def_path_table: Lrc::new(def_path_table), + def_path_table, trait_impls, root: crate_root, blob: metadata, @@ -264,11 +256,9 @@ impl<'a> CrateLoader<'a> { private_dep, raw_proc_macros, dep_node_index: AtomicCell::new(DepNodeIndex::INVALID), - }; + }); - let cmeta = Lrc::new(cmeta); - self.cstore.set_crate_data(cnum, cmeta.clone()); - (cnum, cmeta) + cnum } fn load_proc_macro<'b>( @@ -327,22 +317,22 @@ impl<'a> CrateLoader<'a> { } fn resolve_crate<'b>( - &'b self, + &'b mut self, name: Symbol, span: Span, dep_kind: DepKind, dep: Option<(&'b CratePaths, &'b CrateDep)>, - ) -> (CrateNum, Lrc) { + ) -> CrateNum { self.maybe_resolve_crate(name, span, dep_kind, dep).unwrap_or_else(|err| err.report()) } fn maybe_resolve_crate<'b>( - &'b self, + &'b mut self, name: Symbol, span: Span, mut dep_kind: DepKind, dep: Option<(&'b CratePaths, &'b CrateDep)>, - ) -> Result<(CrateNum, Lrc), LoadError<'b>> { + ) -> Result> { info!("resolving crate `{}`", name); let (root, hash, extra_filename, path_kind) = match dep { Some((root, dep)) => @@ -370,7 +360,7 @@ impl<'a> CrateLoader<'a> { rejected_via_filename: vec![], should_match_name: true, is_proc_macro: Some(false), - metadata_loader: &*self.cstore.metadata_loader, + metadata_loader: self.metadata_loader, }; self.load(&mut locate_ctxt).map(|r| (r, None)).or_else(|| { @@ -388,7 +378,7 @@ impl<'a> CrateLoader<'a> { data.dep_kind.with_lock(|data_dep_kind| { *data_dep_kind = cmp::max(*data_dep_kind, dep_kind); }); - Ok((cnum, data)) + Ok(cnum) } (LoadResult::Loaded(library), host_library) => { Ok(self.register_crate(host_library, root, span, library, dep_kind, name)) @@ -466,7 +456,7 @@ impl<'a> CrateLoader<'a> { } // Go through the crate metadata and load any crates that it references - fn resolve_crate_deps(&self, + fn resolve_crate_deps(&mut self, root: &CratePaths, crate_root: &CrateRoot<'_>, metadata: &MetadataBlob, @@ -492,73 +482,10 @@ impl<'a> CrateLoader<'a> { DepKind::MacrosOnly => DepKind::MacrosOnly, _ => dep.kind, }; - self.resolve_crate(dep.name, span, dep_kind, Some((root, &dep))).0 + self.resolve_crate(dep.name, span, dep_kind, Some((root, &dep))) })).collect() } - fn read_extension_crate(&self, name: Symbol, span: Span) -> ExtensionCrate { - info!("read extension crate `{}`", name); - let target_triple = self.sess.opts.target_triple.clone(); - let host_triple = TargetTriple::from_triple(config::host_triple()); - let is_cross = target_triple != host_triple; - let mut target_only = false; - let mut locate_ctxt = locator::Context { - sess: self.sess, - span, - crate_name: name, - hash: None, - extra_filename: None, - filesearch: self.sess.host_filesearch(PathKind::Crate), - target: &self.sess.host, - triple: host_triple, - root: None, - rejected_via_hash: vec![], - rejected_via_triple: vec![], - rejected_via_kind: vec![], - rejected_via_version: vec![], - rejected_via_filename: vec![], - should_match_name: true, - is_proc_macro: None, - metadata_loader: &*self.cstore.metadata_loader, - }; - let library = self.load(&mut locate_ctxt).or_else(|| { - if !is_cross { - return None - } - // Try loading from target crates. This will abort later if we - // try to load a plugin registrar function, - target_only = true; - - locate_ctxt.target = &self.sess.target.target; - locate_ctxt.triple = target_triple; - locate_ctxt.filesearch = self.sess.target_filesearch(PathKind::Crate); - - self.load(&mut locate_ctxt) - }); - let library = match library { - Some(l) => l, - None => locate_ctxt.report_errs(), - }; - - let (dylib, metadata) = match library { - LoadResult::Previous(cnum) => { - let data = self.cstore.get_crate_data(cnum); - (data.source.dylib.clone(), PMDSource::Registered(data)) - } - LoadResult::Loaded(library) => { - let dylib = library.source.dylib.clone(); - let metadata = PMDSource::Owned(library); - (dylib, metadata) - } - }; - - ExtensionCrate { - metadata, - dylib: dylib.map(|p| p.0), - target_only, - } - } - fn dlsym_proc_macros(&self, path: &Path, disambiguator: CrateDisambiguator, @@ -590,42 +517,7 @@ impl<'a> CrateLoader<'a> { decls } - /// Look for a plugin registrar. Returns library path, crate - /// SVH and DefIndex of the registrar function. - pub fn find_plugin_registrar(&self, - span: Span, - name: Symbol) - -> Option<(PathBuf, CrateDisambiguator)> { - let ekrate = self.read_extension_crate(name, span); - - if ekrate.target_only { - // Need to abort before syntax expansion. - let message = format!("plugin `{}` is not available for triple `{}` \ - (only found {})", - name, - config::host_triple(), - self.sess.opts.target_triple); - span_fatal!(self.sess, span, E0456, "{}", &message); - } - - let root = ekrate.metadata.get_root(); - match ekrate.dylib.as_ref() { - Some(dylib) => { - Some((dylib.to_path_buf(), root.disambiguator)) - } - None => { - span_err!(self.sess, span, E0457, - "plugin `{}` only found in rlib format, but must be available \ - in dylib format", - name); - // No need to abort because the loading code will just ignore this - // empty dylib. - None - } - } - } - - fn inject_panic_runtime(&self, krate: &ast::Crate) { + fn inject_panic_runtime(&mut self, krate: &ast::Crate) { // If we're only compiling an rlib, then there's no need to select a // panic runtime, so we just skip this section entirely. let any_non_rlib = self.sess.crate_types.borrow().iter().any(|ct| { @@ -687,7 +579,8 @@ impl<'a> CrateLoader<'a> { }; info!("panic runtime not found -- loading {}", name); - let (cnum, data) = self.resolve_crate(name, DUMMY_SP, DepKind::Implicit, None); + let cnum = self.resolve_crate(name, DUMMY_SP, DepKind::Implicit, None); + let data = self.cstore.get_crate_data(cnum); // Sanity check the loaded crate to ensure it is indeed a panic runtime // and the panic strategy is indeed what we thought it was. @@ -706,7 +599,7 @@ impl<'a> CrateLoader<'a> { &|data| data.root.needs_panic_runtime); } - fn inject_sanitizer_runtime(&self) { + fn inject_sanitizer_runtime(&mut self) { if let Some(ref sanitizer) = self.sess.opts.debugging_opts.sanitizer { // Sanitizers can only be used on some tested platforms with // executables linked to `std` @@ -791,7 +684,8 @@ impl<'a> CrateLoader<'a> { }); info!("loading sanitizer: {}", name); - let data = self.resolve_crate(name, DUMMY_SP, DepKind::Explicit, None).1; + let cnum = self.resolve_crate(name, DUMMY_SP, DepKind::Explicit, None); + let data = self.cstore.get_crate_data(cnum); // Sanity check the loaded crate to ensure it is indeed a sanitizer runtime if !data.root.sanitizer_runtime { @@ -804,14 +698,15 @@ impl<'a> CrateLoader<'a> { } } - fn inject_profiler_runtime(&self) { + fn inject_profiler_runtime(&mut self) { if self.sess.opts.debugging_opts.profile || self.sess.opts.cg.profile_generate.enabled() { info!("loading profiler"); let name = Symbol::intern("profiler_builtins"); - let data = self.resolve_crate(name, DUMMY_SP, DepKind::Implicit, None).1; + let cnum = self.resolve_crate(name, DUMMY_SP, DepKind::Implicit, None); + let data = self.cstore.get_crate_data(cnum); // Sanity check the loaded crate to ensure it is indeed a profiler runtime if !data.root.profiler_runtime { @@ -957,10 +852,8 @@ impl<'a> CrateLoader<'a> { data.dependencies.borrow_mut().push(krate); }); } -} -impl<'a> CrateLoader<'a> { - pub fn postprocess(&self, krate: &ast::Crate) { + pub fn postprocess(&mut self, krate: &ast::Crate) { self.inject_sanitizer_runtime(); self.inject_profiler_runtime(); self.inject_allocator_crate(krate); @@ -971,7 +864,11 @@ impl<'a> CrateLoader<'a> { } } - pub fn process_extern_crate(&self, item: &ast::Item, definitions: &Definitions) -> CrateNum { + pub fn process_extern_crate( + &mut self, + item: &ast::Item, + definitions: &Definitions, + ) -> CrateNum { match item.kind { ast::ItemKind::ExternCrate(orig_name) => { debug!("resolving extern crate stmt. ident: {} orig_name: {:?}", @@ -990,7 +887,7 @@ impl<'a> CrateLoader<'a> { DepKind::Explicit }; - let cnum = self.resolve_crate(name, item.span, dep_kind, None).0; + let cnum = self.resolve_crate(name, item.span, dep_kind, None); let def_id = definitions.opt_local_def_id(item.id).unwrap(); let path_len = definitions.def_path(def_id.index).data.len(); @@ -1010,8 +907,8 @@ impl<'a> CrateLoader<'a> { } } - pub fn process_path_extern(&self, name: Symbol, span: Span) -> CrateNum { - let cnum = self.resolve_crate(name, span, DepKind::Explicit, None).0; + pub fn process_path_extern(&mut self, name: Symbol, span: Span) -> CrateNum { + let cnum = self.resolve_crate(name, span, DepKind::Explicit, None); self.update_extern_crate( cnum, @@ -1028,8 +925,8 @@ impl<'a> CrateLoader<'a> { cnum } - pub fn maybe_process_path_extern(&self, name: Symbol, span: Span) -> Option { - let cnum = self.maybe_resolve_crate(name, span, DepKind::Explicit, None).ok()?.0; + pub fn maybe_process_path_extern(&mut self, name: Symbol, span: Span) -> Option { + let cnum = self.maybe_resolve_crate(name, span, DepKind::Explicit, None).ok()?; self.update_extern_crate( cnum, diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index 9a0b98ffb73a..6b06cf575edc 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -5,12 +5,13 @@ use crate::schema; use rustc::dep_graph::DepNodeIndex; use rustc::hir::def_id::{CrateNum, DefIndex}; use rustc::hir::map::definitions::DefPathTable; -use rustc::middle::cstore::{CrateSource, DepKind, ExternCrate, MetadataLoader}; +use rustc::middle::cstore::{CrateSource, DepKind, ExternCrate}; use rustc::mir::interpret::AllocDecodingState; use rustc_index::vec::IndexVec; use rustc::util::nodemap::FxHashMap; use rustc_data_structures::sync::{Lrc, RwLock, Lock, MetadataRef, AtomicCell}; use syntax::ast; +use syntax::edition::Edition; use syntax_expand::base::SyntaxExtension; use syntax_pos; use proc_macro::bridge::client::ProcMacro; @@ -36,7 +37,7 @@ crate struct ImportedSourceFile { pub translated_source_file: Lrc, } -pub struct CrateMetadata { +crate struct CrateMetadata { /// The primary crate data - binary metadata blob. crate blob: MetadataBlob, @@ -53,7 +54,7 @@ pub struct CrateMetadata { /// hashmap, which gives the reverse mapping. This allows us to /// quickly retrace a `DefPath`, which is needed for incremental /// compilation support. - crate def_path_table: Lrc, + crate def_path_table: DefPathTable, /// Trait impl data. /// FIXME: Used only from queries and can use query cache, /// so pre-decoding can probably be avoided. @@ -94,50 +95,48 @@ pub struct CrateMetadata { crate extern_crate: Lock>, } +#[derive(Clone)] pub struct CStore { - metas: RwLock>>>, - crate metadata_loader: Box, + metas: IndexVec>>, } pub enum LoadedMacro { - MacroDef(ast::Item), + MacroDef(ast::Item, Edition), ProcMacro(SyntaxExtension), } -impl CStore { - pub fn new(metadata_loader: Box) -> CStore { +impl Default for CStore { + fn default() -> Self { CStore { // We add an empty entry for LOCAL_CRATE (which maps to zero) in // order to make array indices in `metas` match with the // corresponding `CrateNum`. This first entry will always remain // `None`. - metas: RwLock::new(IndexVec::from_elem_n(None, 1)), - metadata_loader, + metas: IndexVec::from_elem_n(None, 1), } } +} - crate fn alloc_new_crate_num(&self) -> CrateNum { - let mut metas = self.metas.borrow_mut(); - let cnum = CrateNum::new(metas.len()); - metas.push(None); - cnum +impl CStore { + crate fn alloc_new_crate_num(&mut self) -> CrateNum { + self.metas.push(None); + CrateNum::new(self.metas.len() - 1) } - crate fn get_crate_data(&self, cnum: CrateNum) -> Lrc { - self.metas.borrow()[cnum].clone() + crate fn get_crate_data(&self, cnum: CrateNum) -> &CrateMetadata { + self.metas[cnum].as_ref() .unwrap_or_else(|| panic!("Failed to get crate data for {:?}", cnum)) } - crate fn set_crate_data(&self, cnum: CrateNum, data: Lrc) { - let mut metas = self.metas.borrow_mut(); - assert!(metas[cnum].is_none(), "Overwriting crate metadata entry"); - metas[cnum] = Some(data); + crate fn set_crate_data(&mut self, cnum: CrateNum, data: CrateMetadata) { + assert!(self.metas[cnum].is_none(), "Overwriting crate metadata entry"); + self.metas[cnum] = Some(Lrc::new(data)); } crate fn iter_crate_data(&self, mut i: I) - where I: FnMut(CrateNum, &Lrc) + where I: FnMut(CrateNum, &CrateMetadata) { - for (k, v) in self.metas.borrow().iter_enumerated() { + for (k, v) in self.metas.iter_enumerated() { if let &Some(ref v) = v { i(k, v); } @@ -168,7 +167,7 @@ impl CStore { crate fn do_postorder_cnums_untracked(&self) -> Vec { let mut ordering = Vec::new(); - for (num, v) in self.metas.borrow().iter_enumerated() { + for (num, v) in self.metas.iter_enumerated() { if let &Some(_) = v { self.push_dependencies_in_postorder(&mut ordering, num); } diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 4cd1ff7b4a4f..d942a19194a1 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -29,7 +29,6 @@ use std::sync::Arc; use syntax::ast; use syntax::attr; use syntax::source_map; -use syntax::edition::Edition; use syntax::parse::source_file_to_stream; use syntax::parse::parser::emit_unclosed_delims; use syntax::source_map::Spanned; @@ -54,7 +53,7 @@ macro_rules! provide { let ($def_id, $other) = def_id_arg.into_args(); assert!(!$def_id.is_local()); - let $cdata = $tcx.crate_data_as_rc_any($def_id.krate); + let $cdata = $tcx.crate_data_as_any($def_id.krate); let $cdata = $cdata.downcast_ref::() .expect("CrateStore created data is not a CrateMetadata"); @@ -411,10 +410,6 @@ impl cstore::CStore { } } - pub fn crate_edition_untracked(&self, cnum: CrateNum) -> Edition { - self.get_crate_data(cnum).root.edition - } - pub fn struct_field_names_untracked(&self, def: DefId, sess: &Session) -> Vec> { self.get_crate_data(def.krate).get_struct_field_names(def.index, sess) } @@ -460,7 +455,7 @@ impl cstore::CStore { LoadedMacro::MacroDef(ast::Item { // FIXME: cross-crate hygiene - ident: ast::Ident::with_dummy_span(name.as_symbol()), + ident: ast::Ident::with_dummy_span(name), id: ast::DUMMY_NODE_ID, span: local_span, attrs: attrs.iter().cloned().collect(), @@ -470,7 +465,7 @@ impl cstore::CStore { }), vis: source_map::respan(local_span.shrink_to_lo(), ast::VisibilityKind::Inherited), tokens: None, - }) + }, data.root.edition) } pub fn associated_item_cloned_untracked(&self, def: DefId) -> ty::AssocItem { @@ -483,8 +478,8 @@ impl cstore::CStore { } impl CrateStore for cstore::CStore { - fn crate_data_as_rc_any(&self, krate: CrateNum) -> Lrc { - self.get_crate_data(krate) + fn crate_data_as_any(&self, cnum: CrateNum) -> &dyn Any { + self.get_crate_data(cnum) } fn item_generics_cloned_untracked(&self, def: DefId, sess: &Session) -> ty::Generics { @@ -525,8 +520,8 @@ impl CrateStore for cstore::CStore { self.get_crate_data(def.krate).def_path_hash(def.index) } - fn def_path_table(&self, cnum: CrateNum) -> Lrc { - self.get_crate_data(cnum).def_path_table.clone() + fn def_path_table(&self, cnum: CrateNum) -> &DefPathTable { + &self.get_crate_data(cnum).def_path_table } fn crates_untracked(&self) -> Vec diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index b8b003024402..8c52168b418f 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -35,7 +35,7 @@ use syntax::ast::{self, Ident}; use syntax::source_map::{self, respan, Spanned}; use syntax::symbol::{Symbol, sym}; use syntax_expand::base::{MacroKind, SyntaxExtensionKind, SyntaxExtension}; -use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP, symbol::{InternedString}}; +use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP}; use log::debug; use proc_macro::bridge::client::ProcMacro; use syntax_expand::proc_macro::{AttrProcMacro, ProcMacroDerive, BangProcMacro}; @@ -448,7 +448,7 @@ impl<'tcx> EntryKind<'tcx> { EntryKind::Mod(_) => DefKind::Mod, EntryKind::Variant(_) => DefKind::Variant, EntryKind::Trait(_) => DefKind::Trait, - EntryKind::TraitAlias(_) => DefKind::TraitAlias, + EntryKind::TraitAlias => DefKind::TraitAlias, EntryKind::Enum(..) => DefKind::Enum, EntryKind::MacroDef(_) => DefKind::Macro(MacroKind::Bang), EntryKind::ForeignType => DefKind::ForeignTy, @@ -458,7 +458,7 @@ impl<'tcx> EntryKind<'tcx> { EntryKind::Impl(_) | EntryKind::Field | EntryKind::Generator(_) | - EntryKind::Closure(_) => return None, + EntryKind::Closure => return None, }) } } @@ -514,7 +514,6 @@ impl<'a, 'tcx> CrateMetadata { .data .get_opt_name() .expect("no name in item_name") - .as_symbol() } else { Symbol::intern(self.raw_proc_macro(item_index).name()) } @@ -575,7 +574,7 @@ impl<'a, 'tcx> CrateMetadata { data.is_marker, self.def_path_table.def_path_hash(item_id)) }, - EntryKind::TraitAlias(_) => { + EntryKind::TraitAlias => { ty::TraitDef::new(self.local_def_id(item_id), hir::Unsafety::Normal, false, @@ -680,13 +679,7 @@ impl<'a, 'tcx> CrateMetadata { item_id: DefIndex, tcx: TyCtxt<'tcx>, ) -> ty::GenericPredicates<'tcx> { - let super_predicates = match self.kind(item_id) { - EntryKind::Trait(data) => data.decode(self).super_predicates, - EntryKind::TraitAlias(data) => data.decode(self).super_predicates, - _ => bug!("def-index does not refer to trait or trait alias"), - }; - - super_predicates.decode((self, tcx)) + self.root.per_def.super_predicates.get(self, item_id).unwrap().decode((self, tcx)) } crate fn get_generics(&self, item_id: DefIndex, sess: &Session) -> ty::Generics { @@ -717,7 +710,7 @@ impl<'a, 'tcx> CrateMetadata { } } - fn get_impl_data(&self, id: DefIndex) -> ImplData<'tcx> { + fn get_impl_data(&self, id: DefIndex) -> ImplData { match self.kind(id) { EntryKind::Impl(data) => data.decode(self), _ => bug!(), @@ -744,7 +737,7 @@ impl<'a, 'tcx> CrateMetadata { } crate fn get_impl_trait(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> Option> { - self.get_impl_data(id).trait_ref.map(|tr| tr.decode((self, tcx))) + self.root.per_def.impl_trait_ref.get(self, id).map(|tr| tr.decode((self, tcx))) } /// Iterates over all the stability attributes in the given crate. @@ -864,7 +857,7 @@ impl<'a, 'tcx> CrateMetadata { let span = self.get_span(child_index, sess); if let (Some(kind), Some(name)) = (self.def_kind(child_index), def_key.disambiguated_data.data.get_opt_name()) { - let ident = Ident::from_interned_str(name); + let ident = Ident::with_dummy_span(name); let vis = self.get_visibility(child_index); let def_id = self.local_def_id(child_index); let res = Res::Def(kind, def_id); @@ -987,7 +980,7 @@ impl<'a, 'tcx> CrateMetadata { }; ty::AssocItem { - ident: Ident::from_interned_str(name), + ident: Ident::with_dummy_span(name), kind, vis: self.get_visibility(id), defaultness: container.defaultness(), @@ -1118,7 +1111,7 @@ impl<'a, 'tcx> CrateMetadata { def_key.parent.and_then(|parent_index| { match self.kind(parent_index) { EntryKind::Trait(_) | - EntryKind::TraitAlias(_) => Some(self.local_def_id(parent_index)), + EntryKind::TraitAlias => Some(self.local_def_id(parent_index)), _ => None, } }) @@ -1245,16 +1238,7 @@ impl<'a, 'tcx> CrateMetadata { } crate fn fn_sig(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> { - let sig = match self.kind(id) { - EntryKind::Fn(data) | - EntryKind::ForeignFn(data) => data.decode(self).sig, - EntryKind::Method(data) => data.decode(self).fn_data.sig, - EntryKind::Variant(data) | - EntryKind::Struct(data, _) => data.decode(self).ctor_sig.unwrap(), - EntryKind::Closure(data) => data.decode(self).sig, - _ => bug!(), - }; - sig.decode((self, tcx)) + self.root.per_def.fn_sig.get(self, id).unwrap().decode((self, tcx)) } #[inline] @@ -1262,7 +1246,7 @@ impl<'a, 'tcx> CrateMetadata { let mut key = self.def_path_table.def_key(index); if self.is_proc_macro(index) { let name = self.raw_proc_macro(index).name(); - key.disambiguated_data.data = DefPathData::MacroNs(InternedString::intern(name)); + key.disambiguated_data.data = DefPathData::MacroNs(Symbol::intern(name)); } key } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 6ae8c2fc6c69..0dc9f91ae00e 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -71,11 +71,14 @@ struct PerDefTables<'tcx> { deprecation: PerDefTable>, ty: PerDefTable>>, + fn_sig: PerDefTable>>, + impl_trait_ref: PerDefTable>>, inherent_impls: PerDefTable>, variances: PerDefTable>, generics: PerDefTable>, predicates: PerDefTable>>, predicates_defined_on: PerDefTable>>, + super_predicates: PerDefTable>>, mir: PerDefTable>>, promoted_mir: PerDefTable>>>, @@ -508,11 +511,14 @@ impl<'tcx> EncodeContext<'tcx> { deprecation: self.per_def.deprecation.encode(&mut self.opaque), ty: self.per_def.ty.encode(&mut self.opaque), + fn_sig: self.per_def.fn_sig.encode(&mut self.opaque), + impl_trait_ref: self.per_def.impl_trait_ref.encode(&mut self.opaque), inherent_impls: self.per_def.inherent_impls.encode(&mut self.opaque), variances: self.per_def.variances.encode(&mut self.opaque), generics: self.per_def.generics.encode(&mut self.opaque), predicates: self.per_def.predicates.encode(&mut self.opaque), predicates_defined_on: self.per_def.predicates_defined_on.encode(&mut self.opaque), + super_predicates: self.per_def.super_predicates.encode(&mut self.opaque), mir: self.per_def.mir.encode(&mut self.opaque), promoted_mir: self.per_def.promoted_mir.encode(&mut self.opaque), @@ -635,13 +641,7 @@ impl EncodeContext<'tcx> { let data = VariantData { ctor_kind: variant.ctor_kind, discr: variant.discr, - // FIXME(eddyb) deduplicate these with `encode_enum_variant_ctor`. ctor: variant.ctor_def_id.map(|did| did.index), - ctor_sig: if variant.ctor_kind == CtorKind::Fn { - variant.ctor_def_id.map(|ctor_def_id| self.lazy(&tcx.fn_sig(ctor_def_id))) - } else { - None - }, }; let enum_id = tcx.hir().as_local_hir_id(enum_did).unwrap(); @@ -660,6 +660,11 @@ impl EncodeContext<'tcx> { self.encode_deprecation(def_id); self.encode_item_type(def_id); if variant.ctor_kind == CtorKind::Fn { + // FIXME(eddyb) encode signature only in `encode_enum_variant_ctor`. + if let Some(ctor_def_id) = variant.ctor_def_id { + record!(self.per_def.fn_sig[def_id] <- tcx.fn_sig(ctor_def_id)); + } + // FIXME(eddyb) is this ever used? self.encode_variances_of(def_id); } self.encode_generics(def_id); @@ -679,15 +684,11 @@ impl EncodeContext<'tcx> { let def_id = variant.ctor_def_id.unwrap(); debug!("EncodeContext::encode_enum_variant_ctor({:?})", def_id); + // FIXME(eddyb) encode only the `CtorKind` for constructors. let data = VariantData { ctor_kind: variant.ctor_kind, discr: variant.discr, ctor: Some(def_id.index), - ctor_sig: if variant.ctor_kind == CtorKind::Fn { - Some(self.lazy(tcx.fn_sig(def_id))) - } else { - None - } }; // Variant constructors have the same visibility as the parent enums, unless marked as @@ -706,6 +707,7 @@ impl EncodeContext<'tcx> { self.encode_deprecation(def_id); self.encode_item_type(def_id); if variant.ctor_kind == CtorKind::Fn { + record!(self.per_def.fn_sig[def_id] <- tcx.fn_sig(def_id)); self.encode_variances_of(def_id); } self.encode_generics(def_id); @@ -780,11 +782,6 @@ impl EncodeContext<'tcx> { ctor_kind: variant.ctor_kind, discr: variant.discr, ctor: Some(def_id.index), - ctor_sig: if variant.ctor_kind == CtorKind::Fn { - Some(self.lazy(tcx.fn_sig(def_id))) - } else { - None - } }; let struct_id = tcx.hir().as_local_hir_id(adt_def_id).unwrap(); @@ -811,6 +808,7 @@ impl EncodeContext<'tcx> { self.encode_deprecation(def_id); self.encode_item_type(def_id); if variant.ctor_kind == CtorKind::Fn { + record!(self.per_def.fn_sig[def_id] <- tcx.fn_sig(def_id)); self.encode_variances_of(def_id); } self.encode_generics(def_id); @@ -835,6 +833,11 @@ impl EncodeContext<'tcx> { self.tcx.predicates_defined_on(def_id)) } + fn encode_super_predicates(&mut self, def_id: DefId) { + debug!("EncodeContext::encode_super_predicates({:?})", def_id); + record!(self.per_def.super_predicates[def_id] <- self.tcx.super_predicates_of(def_id)); + } + fn encode_info_for_trait_item(&mut self, def_id: DefId) { debug!("EncodeContext::encode_info_for_trait_item({:?})", def_id); let tcx = self.tcx; @@ -874,7 +877,6 @@ impl EncodeContext<'tcx> { asyncness: m_sig.header.asyncness, constness: hir::Constness::NotConst, param_names, - sig: self.lazy(tcx.fn_sig(def_id)), } } else { bug!() @@ -906,6 +908,7 @@ impl EncodeContext<'tcx> { ty::AssocKind::OpaqueTy => unreachable!(), } if trait_item.kind == ty::AssocKind::Method { + record!(self.per_def.fn_sig[def_id] <- tcx.fn_sig(def_id)); self.encode_variances_of(def_id); } self.encode_generics(def_id); @@ -952,7 +955,6 @@ impl EncodeContext<'tcx> { asyncness: sig.header.asyncness, constness: sig.header.constness, param_names: self.encode_fn_param_names_for_body(body), - sig: self.lazy(tcx.fn_sig(def_id)), } } else { bug!() @@ -973,6 +975,7 @@ impl EncodeContext<'tcx> { self.encode_deprecation(def_id); self.encode_item_type(def_id); if impl_item.kind == ty::AssocKind::Method { + record!(self.per_def.fn_sig[def_id] <- tcx.fn_sig(def_id)); self.encode_variances_of(def_id); } self.encode_generics(def_id); @@ -1081,7 +1084,6 @@ impl EncodeContext<'tcx> { asyncness: header.asyncness, constness: header.constness, param_names: self.encode_fn_param_names_for_body(body), - sig: self.lazy(tcx.fn_sig(def_id)), }; EntryKind::Fn(self.lazy(data)) @@ -1109,7 +1111,6 @@ impl EncodeContext<'tcx> { ctor_kind: variant.ctor_kind, discr: variant.discr, ctor, - ctor_sig: None, }), adt_def.repr) } hir::ItemKind::Union(..) => { @@ -1120,7 +1121,6 @@ impl EncodeContext<'tcx> { ctor_kind: variant.ctor_kind, discr: variant.discr, ctor: None, - ctor_sig: None, }), adt_def.repr) } hir::ItemKind::Impl(_, _, defaultness, ..) => { @@ -1154,7 +1154,6 @@ impl EncodeContext<'tcx> { defaultness, parent_impl: parent, coerce_unsized_info, - trait_ref: trait_ref.map(|trait_ref| self.lazy(trait_ref)), }; EntryKind::Impl(self.lazy(data)) @@ -1166,18 +1165,11 @@ impl EncodeContext<'tcx> { paren_sugar: trait_def.paren_sugar, has_auto_impl: self.tcx.trait_is_auto(def_id), is_marker: trait_def.is_marker, - super_predicates: self.lazy(tcx.super_predicates_of(def_id)), }; EntryKind::Trait(self.lazy(data)) } - hir::ItemKind::TraitAlias(..) => { - let data = TraitAliasData { - super_predicates: self.lazy(tcx.super_predicates_of(def_id)), - }; - - EntryKind::TraitAlias(self.lazy(data)) - } + hir::ItemKind::TraitAlias(..) => EntryKind::TraitAlias, hir::ItemKind::ExternCrate(_) | hir::ItemKind::Use(..) => bug!("cannot encode info for item {:?}", item), }); @@ -1232,6 +1224,14 @@ impl EncodeContext<'tcx> { hir::ItemKind::Impl(..) => self.encode_item_type(def_id), _ => {} } + if let hir::ItemKind::Fn(..) = item.kind { + record!(self.per_def.fn_sig[def_id] <- tcx.fn_sig(def_id)); + } + if let hir::ItemKind::Impl(..) = item.kind { + if let Some(trait_ref) = self.tcx.impl_trait_ref(def_id) { + record!(self.per_def.impl_trait_ref[def_id] <- trait_ref); + } + } self.encode_inherent_implementations(def_id); match item.kind { hir::ItemKind::Enum(..) | @@ -1269,6 +1269,13 @@ impl EncodeContext<'tcx> { } _ => {} // not *wrong* for other kinds of items, but not needed } + match item.kind { + hir::ItemKind::Trait(..) | + hir::ItemKind::TraitAlias(..) => { + self.encode_super_predicates(def_id); + } + _ => {} + } let mir = match item.kind { hir::ItemKind::Static(..) | hir::ItemKind::Const(..) => true, @@ -1321,10 +1328,12 @@ impl EncodeContext<'tcx> { fn encode_info_for_closure(&mut self, def_id: DefId) { debug!("EncodeContext::encode_info_for_closure({:?})", def_id); - let tables = self.tcx.typeck_tables_of(def_id); + // NOTE(eddyb) `tcx.type_of(def_id)` isn't used because it's fully generic, + // including on the signature, which is inferred in `typeck_tables_of. let hir_id = self.tcx.hir().as_local_hir_id(def_id).unwrap(); + let ty = self.tcx.typeck_tables_of(def_id).node_type(hir_id); - record!(self.per_def.kind[def_id] <- match tables.node_type(hir_id).kind { + record!(self.per_def.kind[def_id] <- match ty.kind { ty::Generator(def_id, ..) => { let layout = self.tcx.generator_layout(def_id); let data = GeneratorData { @@ -1333,11 +1342,7 @@ impl EncodeContext<'tcx> { EntryKind::Generator(self.lazy(data)) } - ty::Closure(def_id, substs) => { - let sig = substs.as_closure().sig(def_id, self.tcx); - let data = ClosureData { sig: self.lazy(sig) }; - EntryKind::Closure(self.lazy(data)) - } + ty::Closure(..) => EntryKind::Closure, _ => bug!("closure that is neither generator nor closure"), }); @@ -1345,6 +1350,9 @@ impl EncodeContext<'tcx> { record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id)); record!(self.per_def.attributes[def_id] <- &self.tcx.get_attrs(def_id)[..]); self.encode_item_type(def_id); + if let ty::Closure(def_id, substs) = ty.kind { + record!(self.per_def.fn_sig[def_id] <- substs.as_closure().sig(def_id, self.tcx)); + } self.encode_generics(def_id); self.encode_optimized_mir(def_id); self.encode_promoted_mir(def_id); @@ -1553,7 +1561,6 @@ impl EncodeContext<'tcx> { asyncness: hir::IsAsync::NotAsync, constness: hir::Constness::NotConst, param_names: self.encode_fn_param_names(names), - sig: self.lazy(tcx.fn_sig(def_id)), }; EntryKind::ForeignFn(self.lazy(data)) } @@ -1569,6 +1576,7 @@ impl EncodeContext<'tcx> { self.encode_deprecation(def_id); self.encode_item_type(def_id); if let hir::ForeignItemKind::Fn(..) = nitem.kind { + record!(self.per_def.fn_sig[def_id] <- tcx.fn_sig(def_id)); self.encode_variances_of(def_id); } self.encode_generics(def_id); diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs index 05676dad3340..a5298402dd41 100644 --- a/src/librustc_metadata/locator.rs +++ b/src/librustc_metadata/locator.rs @@ -212,7 +212,7 @@ //! no means all of the necessary details. Take a look at the rest of //! metadata::locator or metadata::creader for all the juicy details! -use crate::cstore::{MetadataBlob, CStore}; +use crate::cstore::MetadataBlob; use crate::creader::Library; use crate::schema::{METADATA_HEADER, rustc_version}; @@ -220,12 +220,13 @@ use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::MetadataRef; use rustc::middle::cstore::{CrateSource, MetadataLoader}; -use rustc::session::{config, Session}; +use rustc::session::{config, Session, CrateDisambiguator}; use rustc::session::filesearch::{FileSearch, FileMatches, FileDoesntMatch}; use rustc::session::search_paths::PathKind; use rustc::util::nodemap::FxHashMap; use errors::DiagnosticBuilder; +use syntax::{span_err, span_fatal}; use syntax::symbol::{Symbol, sym}; use syntax::struct_span_err; use syntax_pos::Span; @@ -911,10 +912,87 @@ fn get_metadata_section_imp(target: &Target, } } +/// Look for a plugin registrar. Returns its library path and crate disambiguator. +pub fn find_plugin_registrar( + sess: &Session, + metadata_loader: &dyn MetadataLoader, + span: Span, + name: Symbol, +) -> Option<(PathBuf, CrateDisambiguator)> { + info!("find plugin registrar `{}`", name); + let target_triple = sess.opts.target_triple.clone(); + let host_triple = TargetTriple::from_triple(config::host_triple()); + let is_cross = target_triple != host_triple; + let mut target_only = false; + let mut locate_ctxt = Context { + sess, + span, + crate_name: name, + hash: None, + extra_filename: None, + filesearch: sess.host_filesearch(PathKind::Crate), + target: &sess.host, + triple: host_triple, + root: None, + rejected_via_hash: vec![], + rejected_via_triple: vec![], + rejected_via_kind: vec![], + rejected_via_version: vec![], + rejected_via_filename: vec![], + should_match_name: true, + is_proc_macro: None, + metadata_loader, + }; + + let library = locate_ctxt.maybe_load_library_crate().or_else(|| { + if !is_cross { + return None + } + // Try loading from target crates. This will abort later if we + // try to load a plugin registrar function, + target_only = true; + + locate_ctxt.target = &sess.target.target; + locate_ctxt.triple = target_triple; + locate_ctxt.filesearch = sess.target_filesearch(PathKind::Crate); + + locate_ctxt.maybe_load_library_crate() + }); + let library = match library { + Some(l) => l, + None => locate_ctxt.report_errs(), + }; + + if target_only { + // Need to abort before syntax expansion. + let message = format!("plugin `{}` is not available for triple `{}` \ + (only found {})", + name, + config::host_triple(), + sess.opts.target_triple); + span_fatal!(sess, span, E0456, "{}", &message); + } + + match library.source.dylib { + Some(dylib) => { + Some((dylib.0, library.metadata.get_root().disambiguator)) + } + None => { + span_err!(sess, span, E0457, + "plugin `{}` only found in rlib format, but must be available \ + in dylib format", + name); + // No need to abort because the loading code will just ignore this + // empty dylib. + None + } + } +} + /// A diagnostic function for dumping crate metadata to an output stream. pub fn list_file_metadata(target: &Target, path: &Path, - cstore: &CStore, + metadata_loader: &dyn MetadataLoader, out: &mut dyn io::Write) -> io::Result<()> { let filename = path.file_name().unwrap().to_str().unwrap(); @@ -925,7 +1003,7 @@ pub fn list_file_metadata(target: &Target, } else { CrateFlavor::Dylib }; - match get_metadata_section(target, flavor, path, &*cstore.metadata_loader) { + match get_metadata_section(target, flavor, path, metadata_loader) { Ok(metadata) => metadata.list_crate_metadata(out), Err(msg) => write!(out, "{}\n", msg), } diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 96f35783278f..ad39aa34fd5c 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -238,11 +238,14 @@ crate struct LazyPerDefTables<'tcx> { pub deprecation: Lazy!(PerDefTable>), pub ty: Lazy!(PerDefTable)>), + pub fn_sig: Lazy!(PerDefTable)>), + pub impl_trait_ref: Lazy!(PerDefTable)>), pub inherent_impls: Lazy!(PerDefTable>), pub variances: Lazy!(PerDefTable>), pub generics: Lazy!(PerDefTable>), pub predicates: Lazy!(PerDefTable)>), pub predicates_defined_on: Lazy!(PerDefTable)>), + pub super_predicates: Lazy!(PerDefTable)>), pub mir: Lazy!(PerDefTable)>), pub promoted_mir: Lazy!(PerDefTable>)>), @@ -264,22 +267,22 @@ crate enum EntryKind<'tcx> { OpaqueTy, Enum(ReprOptions), Field, - Variant(Lazy!(VariantData<'tcx>)), - Struct(Lazy!(VariantData<'tcx>), ReprOptions), - Union(Lazy!(VariantData<'tcx>), ReprOptions), - Fn(Lazy!(FnData<'tcx>)), - ForeignFn(Lazy!(FnData<'tcx>)), + Variant(Lazy), + Struct(Lazy, ReprOptions), + Union(Lazy, ReprOptions), + Fn(Lazy), + ForeignFn(Lazy), Mod(Lazy), MacroDef(Lazy), - Closure(Lazy!(ClosureData<'tcx>)), + Closure, Generator(Lazy!(GeneratorData<'tcx>)), - Trait(Lazy!(TraitData<'tcx>)), - Impl(Lazy!(ImplData<'tcx>)), - Method(Lazy!(MethodData<'tcx>)), + Trait(Lazy), + Impl(Lazy), + Method(Lazy), AssocType(AssocContainer), AssocOpaqueTy(AssocContainer), AssocConst(AssocContainer, ConstQualif, Lazy), - TraitAlias(Lazy!(TraitAliasData<'tcx>)), + TraitAlias, } /// Additional data for EntryKind::Const and EntryKind::AssocConst @@ -305,47 +308,37 @@ crate struct MacroDef { } #[derive(RustcEncodable, RustcDecodable)] -crate struct FnData<'tcx> { +crate struct FnData { pub asyncness: hir::IsAsync, pub constness: hir::Constness, pub param_names: Lazy<[ast::Name]>, - pub sig: Lazy!(ty::PolyFnSig<'tcx>), } #[derive(RustcEncodable, RustcDecodable)] -crate struct VariantData<'tcx> { +crate struct VariantData { pub ctor_kind: CtorKind, pub discr: ty::VariantDiscr, /// If this is unit or tuple-variant/struct, then this is the index of the ctor id. pub ctor: Option, - /// If this is a tuple struct or variant - /// ctor, this is its "function" signature. - pub ctor_sig: Option)>, } #[derive(RustcEncodable, RustcDecodable)] -crate struct TraitData<'tcx> { +crate struct TraitData { pub unsafety: hir::Unsafety, pub paren_sugar: bool, pub has_auto_impl: bool, pub is_marker: bool, - pub super_predicates: Lazy!(ty::GenericPredicates<'tcx>), } #[derive(RustcEncodable, RustcDecodable)] -crate struct TraitAliasData<'tcx> { - pub super_predicates: Lazy!(ty::GenericPredicates<'tcx>), -} - -#[derive(RustcEncodable, RustcDecodable)] -crate struct ImplData<'tcx> { +crate struct ImplData { pub polarity: ty::ImplPolarity, pub defaultness: hir::Defaultness, pub parent_impl: Option, /// This is `Some` only for impls of `CoerceUnsized`. + // FIXME(eddyb) perhaps compute this on the fly if cheap enough? pub coerce_unsized_info: Option, - pub trait_ref: Option)>, } @@ -388,17 +381,12 @@ impl AssocContainer { } #[derive(RustcEncodable, RustcDecodable)] -crate struct MethodData<'tcx> { - pub fn_data: FnData<'tcx>, +crate struct MethodData { + pub fn_data: FnData, pub container: AssocContainer, pub has_self: bool, } -#[derive(RustcEncodable, RustcDecodable)] -crate struct ClosureData<'tcx> { - pub sig: Lazy!(ty::PolyFnSig<'tcx>), -} - #[derive(RustcEncodable, RustcDecodable)] crate struct GeneratorData<'tcx> { pub layout: mir::GeneratorLayout<'tcx>, diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs index 6fb976e0d84b..d6e84940291a 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs @@ -18,14 +18,14 @@ use rustc::ty::print::RegionHighlightMode; use rustc_errors::DiagnosticBuilder; use syntax::symbol::kw; use rustc_data_structures::fx::FxHashMap; -use syntax_pos::{Span, symbol::InternedString}; +use syntax_pos::{Span, symbol::Symbol}; /// A name for a particular region used in emitting diagnostics. This name could be a generated /// name like `'1`, a name used by the user like `'a`, or a name like `'static`. #[derive(Debug, Clone)] crate struct RegionName { /// The name of the region (interned). - crate name: InternedString, + crate name: Symbol, /// Where the region comes from. crate source: RegionNameSource, } @@ -109,7 +109,7 @@ impl RegionName { } #[allow(dead_code)] - crate fn name(&self) -> InternedString { + crate fn name(&self) -> Symbol { self.name } @@ -273,7 +273,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { } ty::ReStatic => Some(RegionName { - name: kw::StaticLifetime.as_interned_str(), + name: kw::StaticLifetime, source: RegionNameSource::Static }), @@ -360,7 +360,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { &self, tcx: TyCtxt<'tcx>, error_region: &RegionKind, - name: InternedString, + name: Symbol, ) -> Span { let scope = error_region.free_region_binding_scope(tcx); let node = tcx.hir().as_local_hir_id(scope).unwrap_or(hir::DUMMY_HIR_ID); @@ -837,10 +837,10 @@ impl<'tcx> RegionInferenceContext<'tcx> { } /// Creates a synthetic region named `'1`, incrementing the counter. - fn synthesize_region_name(&self, renctx: &mut RegionErrorNamingCtx) -> InternedString { + fn synthesize_region_name(&self, renctx: &mut RegionErrorNamingCtx) -> Symbol { let c = renctx.counter; renctx.counter += 1; - InternedString::intern(&format!("'{:?}", c)) + Symbol::intern(&format!("'{:?}", c)) } } diff --git a/src/librustc_mir/borrow_check/nll/universal_regions.rs b/src/librustc_mir/borrow_check/nll/universal_regions.rs index fd1f333010ad..b876fd83ec98 100644 --- a/src/librustc_mir/borrow_check/nll/universal_regions.rs +++ b/src/librustc_mir/borrow_check/nll/universal_regions.rs @@ -790,7 +790,7 @@ fn for_each_late_bound_region_defined_on<'tcx>( owner: fn_def_id.index, local_id: *late_bound, }; - let name = tcx.hir().name(hir_id).as_interned_str(); + let name = tcx.hir().name(hir_id); let region_def_id = tcx.hir().local_def_id(hir_id); let liberated_region = tcx.mk_region(ty::ReFree(ty::FreeRegion { scope: fn_def_id, diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index e6f7a042f1c2..7bb96661bb74 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -908,7 +908,7 @@ fn convert_path_expr<'a, 'tcx>( let generics = cx.tcx.generics_of(item_def_id); let local_def_id = cx.tcx.hir().local_def_id(hir_id); let index = generics.param_def_id_to_index[&local_def_id]; - let name = cx.tcx.hir().name(hir_id).as_interned_str(); + let name = cx.tcx.hir().name(hir_id); let val = ConstValue::Param(ty::ParamConst::new(index, name)); ExprKind::Literal { literal: cx.tcx.mk_const( diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 58480912929b..98e286e61e94 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -25,7 +25,6 @@ use rustc::hir::pat_util::EnumerateAndAdjustIterator; use rustc::hir::ptr::P; use rustc_index::vec::Idx; -use rustc_data_structures::fx::FxHashSet; use std::cmp::Ordering; use std::fmt; @@ -1000,15 +999,21 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { if self.include_lint_checks && !saw_error { // If we were able to successfully convert the const to some pat, double-check // that the type of the const obeys `#[structural_match]` constraint. - if let Some(adt_def) = search_for_adt_without_structural_match(self.tcx, cv.ty) { - - let path = self.tcx.def_path_str(adt_def.did); - let msg = format!( - "to use a constant of type `{}` in a pattern, \ - `{}` must be annotated with `#[derive(PartialEq, Eq)]`", - path, - path, - ); + if let Some(non_sm_ty) = ty::search_for_structural_match_violation(self.tcx, cv.ty) { + let msg = match non_sm_ty { + ty::NonStructuralMatchTy::Adt(adt_def) => { + let path = self.tcx.def_path_str(adt_def.did); + format!( + "to use a constant of type `{}` in a pattern, \ + `{}` must be annotated with `#[derive(PartialEq, Eq)]`", + path, + path, + ) + } + ty::NonStructuralMatchTy::Param => { + bug!("use of constant whose type is a parameter inside a pattern"); + } + }; // before issuing lint, double-check there even *is* a // semantic PartialEq for us to dispatch to. @@ -1169,125 +1174,6 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { } } -/// This method traverses the structure of `ty`, trying to find an -/// instance of an ADT (i.e. struct or enum) that was declared without -/// the `#[structural_match]` attribute. -/// -/// The "structure of a type" includes all components that would be -/// considered when doing a pattern match on a constant of that -/// type. -/// -/// * This means this method descends into fields of structs/enums, -/// and also descends into the inner type `T` of `&T` and `&mut T` -/// -/// * The traversal doesn't dereference unsafe pointers (`*const T`, -/// `*mut T`), and it does not visit the type arguments of an -/// instantiated generic like `PhantomData`. -/// -/// The reason we do this search is Rust currently require all ADT's -/// reachable from a constant's type to be annotated with -/// `#[structural_match]`, an attribute which essentially says that -/// the implementation of `PartialEq::eq` behaves *equivalently* to a -/// comparison against the unfolded structure. -/// -/// For more background on why Rust has this requirement, and issues -/// that arose when the requirement was not enforced completely, see -/// Rust RFC 1445, rust-lang/rust#61188, and rust-lang/rust#62307. -fn search_for_adt_without_structural_match<'tcx>(tcx: TyCtxt<'tcx>, - ty: Ty<'tcx>) - -> Option<&'tcx AdtDef> -{ - // Import here (not mod level), because `TypeFoldable::fold_with` - // conflicts with `PatternFoldable::fold_with` - use crate::rustc::ty::fold::TypeVisitor; - use crate::rustc::ty::TypeFoldable; - - let mut search = Search { tcx, found: None, seen: FxHashSet::default() }; - ty.visit_with(&mut search); - return search.found; - - struct Search<'tcx> { - tcx: TyCtxt<'tcx>, - - // records the first ADT we find without `#[structural_match` - found: Option<&'tcx AdtDef>, - - // tracks ADT's previously encountered during search, so that - // we will not recur on them again. - seen: FxHashSet, - } - - impl<'tcx> TypeVisitor<'tcx> for Search<'tcx> { - fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { - debug!("Search visiting ty: {:?}", ty); - - let (adt_def, substs) = match ty.kind { - ty::Adt(adt_def, substs) => (adt_def, substs), - ty::RawPtr(..) => { - // `#[structural_match]` ignores substructure of - // `*const _`/`*mut _`, so skip super_visit_with - // - // (But still tell caller to continue search.) - return false; - } - ty::FnDef(..) | ty::FnPtr(..) => { - // types of formals and return in `fn(_) -> _` are also irrelevant - // - // (But still tell caller to continue search.) - return false; - } - ty::Array(_, n) if n.try_eval_usize(self.tcx, ty::ParamEnv::reveal_all()) == Some(0) - => { - // rust-lang/rust#62336: ignore type of contents - // for empty array. - return false; - } - _ => { - ty.super_visit_with(self); - return false; - } - }; - - if !self.tcx.has_attr(adt_def.did, sym::structural_match) { - self.found = Some(&adt_def); - debug!("Search found adt_def: {:?}", adt_def); - return true // Halt visiting! - } - - if !self.seen.insert(adt_def.did) { - debug!("Search already seen adt_def: {:?}", adt_def); - // let caller continue its search - return false; - } - - // `#[structural_match]` does not care about the - // instantiation of the generics in an ADT (it - // instead looks directly at its fields outside - // this match), so we skip super_visit_with. - // - // (Must not recur on substs for `PhantomData` cf - // rust-lang/rust#55028 and rust-lang/rust#55837; but also - // want to skip substs when only uses of generic are - // behind unsafe pointers `*const T`/`*mut T`.) - - // even though we skip super_visit_with, we must recur on - // fields of ADT. - let tcx = self.tcx; - for field_ty in adt_def.all_fields().map(|field| field.ty(tcx, substs)) { - if field_ty.visit_with(self) { - // found an ADT without `#[structural_match]`; halt visiting! - assert!(self.found.is_some()); - return true; - } - } - - // Even though we do not want to recur on substs, we do - // want our caller to continue its own search. - false - } - } -} - impl UserAnnotatedTyHelpers<'tcx> for PatCtxt<'_, 'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 2ab7c41bb787..d929e958f05d 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -91,7 +91,7 @@ pub struct Frame<'mir, 'tcx, Tag=(), Extra=()> { pub extra: Extra, } -#[derive(Clone, Eq, PartialEq)] +#[derive(Clone, Eq, PartialEq, Debug)] // Miri debug-prints these pub enum StackPopCleanup { /// Jump to the next block in the caller, or cause UB if None (that's a function /// that may never return). Also store layout of return place so @@ -113,7 +113,7 @@ pub struct LocalState<'tcx, Tag=(), Id=AllocId> { } /// Current value of a local variable -#[derive(Clone, PartialEq, Eq)] +#[derive(Clone, PartialEq, Eq, Debug)] // Miri debug-prints these pub enum LocalValue { /// This local is not currently alive, and cannot be used at all. Dead, diff --git a/src/librustc_mir/interpret/intrinsics/type_name.rs b/src/librustc_mir/interpret/intrinsics/type_name.rs index f9200f8c1c04..f1f9fac08ca3 100644 --- a/src/librustc_mir/interpret/intrinsics/type_name.rs +++ b/src/librustc_mir/interpret/intrinsics/type_name.rs @@ -148,7 +148,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { self.path.push_str("::"); - self.path.push_str(&disambiguated_data.data.as_interned_str().as_str()); + self.path.push_str(&disambiguated_data.data.as_symbol().as_str()); Ok(self) } diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index eef1868ec65b..d113ee33162d 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -7,7 +7,7 @@ //! short-circuiting the empty case! use std::collections::VecDeque; -use std::{ptr, iter}; +use std::ptr; use std::borrow::Cow; use rustc::ty::{self, Instance, ParamEnv, query::TyCtxtAt}; @@ -791,11 +791,12 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { pub fn write_bytes( &mut self, ptr: Scalar, - src: impl IntoIterator, + src: impl IntoIterator, ) -> InterpResult<'tcx> { let src = src.into_iter(); - let size = Size::from_bytes(src.len() as u64); + let size = Size::from_bytes(src.size_hint().0 as u64); + // `write_bytes` checks that this lower bound matches the upper bound matches reality. let ptr = match self.check_ptr_access(ptr, size, Align::from_bytes(1).unwrap())? { Some(ptr) => ptr, None => return Ok(()), // zero-sized access diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs index b9d38028b72a..42f08771f866 100644 --- a/src/librustc_mir/monomorphize/partitioning.rs +++ b/src/librustc_mir/monomorphize/partitioning.rs @@ -96,7 +96,7 @@ use std::collections::hash_map::Entry; use std::cmp; use std::sync::Arc; -use syntax::symbol::InternedString; +use syntax::symbol::Symbol; use rustc::hir::CodegenFnAttrFlags; use rustc::hir::def::DefKind; use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE, CRATE_DEF_INDEX}; @@ -121,7 +121,7 @@ pub enum PartitioningStrategy { } // Anything we can't find a proper codegen unit for goes into this. -fn fallback_cgu_name(name_builder: &mut CodegenUnitNameBuilder<'_>) -> InternedString { +fn fallback_cgu_name(name_builder: &mut CodegenUnitNameBuilder<'_>) -> Symbol { name_builder.build_cgu_name(LOCAL_CRATE, &["fallback"], Some("cgu")) } @@ -185,9 +185,7 @@ where internalization_candidates: _, } = post_inlining; - result.sort_by(|cgu1, cgu2| { - cgu1.name().cmp(cgu2.name()) - }); + result.sort_by_cached_key(|cgu| cgu.name().as_str()); result } @@ -203,7 +201,7 @@ struct PreInliningPartitioning<'tcx> { /// to keep track of that. #[derive(Clone, PartialEq, Eq, Debug)] enum MonoItemPlacement { - SingleCgu { cgu_name: InternedString }, + SingleCgu { cgu_name: Symbol }, MultipleCgus, } @@ -251,8 +249,8 @@ where None => fallback_cgu_name(cgu_name_builder), }; - let codegen_unit = codegen_units.entry(codegen_unit_name.clone()) - .or_insert_with(|| CodegenUnit::new(codegen_unit_name.clone())); + let codegen_unit = codegen_units.entry(codegen_unit_name) + .or_insert_with(|| CodegenUnit::new(codegen_unit_name)); let mut can_be_internalized = true; let (linkage, visibility) = mono_item_linkage_and_visibility( @@ -273,8 +271,7 @@ where // crate with just types (for example), we could wind up with no CGU. if codegen_units.is_empty() { let codegen_unit_name = fallback_cgu_name(cgu_name_builder); - codegen_units.insert(codegen_unit_name.clone(), - CodegenUnit::new(codegen_unit_name.clone())); + codegen_units.insert(codegen_unit_name, CodegenUnit::new(codegen_unit_name)); } PreInliningPartitioning { @@ -492,7 +489,7 @@ fn merge_codegen_units<'tcx>( // smallest into each other) we're sure to start off with a deterministic // order (sorted by name). This'll mean that if two cgus have the same size // the stable sort below will keep everything nice and deterministic. - codegen_units.sort_by_key(|cgu| *cgu.name()); + codegen_units.sort_by_cached_key(|cgu| cgu.name().as_str()); // Merge the two smallest codegen units until the target size is reached. while codegen_units.len() > target_cgu_count { @@ -537,7 +534,7 @@ fn place_inlined_mono_items<'tcx>(initial_partitioning: PreInliningPartitioning< follow_inlining(*root, inlining_map, &mut reachable); } - let mut new_codegen_unit = CodegenUnit::new(old_codegen_unit.name().clone()); + let mut new_codegen_unit = CodegenUnit::new(old_codegen_unit.name()); // Add all monomorphizations that are not already there. for mono_item in reachable { @@ -564,8 +561,8 @@ fn place_inlined_mono_items<'tcx>(initial_partitioning: PreInliningPartitioning< Entry::Occupied(e) => { let placement = e.into_mut(); debug_assert!(match *placement { - MonoItemPlacement::SingleCgu { ref cgu_name } => { - *cgu_name != *new_codegen_unit.name() + MonoItemPlacement::SingleCgu { cgu_name } => { + cgu_name != new_codegen_unit.name() } MonoItemPlacement::MultipleCgus => true, }); @@ -573,7 +570,7 @@ fn place_inlined_mono_items<'tcx>(initial_partitioning: PreInliningPartitioning< } Entry::Vacant(e) => { e.insert(MonoItemPlacement::SingleCgu { - cgu_name: new_codegen_unit.name().clone() + cgu_name: new_codegen_unit.name() }); } } @@ -638,7 +635,7 @@ fn internalize_symbols<'tcx>( // accessed from outside its defining codegen unit. for cgu in &mut partitioning.codegen_units { let home_cgu = MonoItemPlacement::SingleCgu { - cgu_name: cgu.name().clone() + cgu_name: cgu.name() }; for (accessee, linkage_and_visibility) in cgu.items_mut() { @@ -717,7 +714,7 @@ fn characteristic_def_id_of_mono_item<'tcx>( } } -type CguNameCache = FxHashMap<(DefId, bool), InternedString>; +type CguNameCache = FxHashMap<(DefId, bool), Symbol>; fn compute_codegen_unit_name( tcx: TyCtxt<'_>, @@ -725,7 +722,7 @@ fn compute_codegen_unit_name( def_id: DefId, volatile: bool, cache: &mut CguNameCache, -) -> InternedString { +) -> Symbol { // Find the innermost module that is not nested within a function. let mut current_def_id = def_id; let mut cgu_def_id = None; @@ -762,7 +759,7 @@ fn compute_codegen_unit_name( let components = def_path .data .iter() - .map(|part| part.data.as_interned_str()); + .map(|part| part.data.as_symbol()); let volatile_suffix = if volatile { Some("volatile") @@ -777,7 +774,7 @@ fn compute_codegen_unit_name( fn numbered_codegen_unit_name( name_builder: &mut CodegenUnitNameBuilder<'_>, index: usize, -) -> InternedString { +) -> Symbol { name_builder.build_cgu_name_no_mangle(LOCAL_CRATE, &["cgu"], Some(index)) } @@ -929,7 +926,7 @@ fn collect_and_partition_mono_items( for (&mono_item, &linkage) in cgu.items() { item_to_cgus.entry(mono_item) .or_default() - .push((cgu.name().clone(), linkage)); + .push((cgu.name(), linkage)); } } @@ -991,7 +988,7 @@ pub fn provide(providers: &mut Providers<'_>) { providers.codegen_unit = |tcx, name| { let (_, all) = tcx.collect_and_partition_mono_items(LOCAL_CRATE); all.iter() - .find(|cgu| *cgu.name() == name) + .find(|cgu| cgu.name() == name) .cloned() .unwrap_or_else(|| panic!("failed to find cgu with name {:?}", name)) }; diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index 70855d70228b..3ff36e01275b 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -12,7 +12,7 @@ use rustc::lint::builtin::{SAFE_EXTERN_STATICS, SAFE_PACKED_BORROWS, UNUSED_UNSA use rustc::mir::*; use rustc::mir::visit::{PlaceContext, Visitor, MutatingUseContext}; -use syntax::symbol::{InternedString, sym}; +use syntax::symbol::{Symbol, sym}; use std::ops::Bound; @@ -167,9 +167,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { (CastTy::FnPtr, CastTy::Int(_)) => { self.register_violations(&[UnsafetyViolation { source_info: self.source_info, - description: InternedString::intern("cast of pointer to int"), - details: InternedString::intern( - "casting pointers to integers in constants"), + description: Symbol::intern("cast of pointer to int"), + details: Symbol::intern("casting pointers to integers in constants"), kind: UnsafetyViolationKind::General, }], &[]); }, @@ -185,8 +184,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { if let ty::RawPtr(_) | ty::FnPtr(..) = lhs.ty(self.body, self.tcx).kind { self.register_violations(&[UnsafetyViolation { source_info: self.source_info, - description: InternedString::intern("pointer operation"), - details: InternedString::intern("operations on pointers in constants"), + description: Symbol::intern("pointer operation"), + details: Symbol::intern("operations on pointers in constants"), kind: UnsafetyViolationKind::General, }], &[]); } @@ -219,8 +218,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { self.source_scope_local_data[source_info.scope].lint_root; self.register_violations(&[UnsafetyViolation { source_info, - description: InternedString::intern("use of extern static"), - details: InternedString::intern( + description: Symbol::intern("use of extern static"), + details: Symbol::intern( "extern statics are not controlled by the Rust type system: \ invalid data, aliasing violations or data races will cause \ undefined behavior"), @@ -240,8 +239,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { self.source_scope_local_data[source_info.scope].lint_root; self.register_violations(&[UnsafetyViolation { source_info, - description: InternedString::intern("borrow of packed field"), - details: InternedString::intern( + description: Symbol::intern("borrow of packed field"), + details: Symbol::intern( "fields of packed structs might be misaligned: dereferencing a \ misaligned pointer or even just creating a misaligned reference \ is undefined behavior"), @@ -334,8 +333,8 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { let source_info = self.source_info; self.register_violations(&[UnsafetyViolation { source_info, - description: InternedString::intern(description), - details: InternedString::intern(details), + description: Symbol::intern(description), + details: Symbol::intern(details), kind, }], &[]); } @@ -438,8 +437,8 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { let source_info = self.source_info; self.register_violations(&[UnsafetyViolation { source_info, - description: InternedString::intern(description), - details: InternedString::intern(details), + description: Symbol::intern(description), + details: Symbol::intern(details), kind: UnsafetyViolationKind::GeneralAndConstFn, }], &[]); } diff --git a/src/librustc_plugin/load.rs b/src/librustc_plugin/load.rs index 4481892bcf24..8ceb56b0fd2b 100644 --- a/src/librustc_plugin/load.rs +++ b/src/librustc_plugin/load.rs @@ -1,8 +1,8 @@ //! Used by `rustc` when loading a plugin. +use rustc::middle::cstore::MetadataLoader; use rustc::session::Session; -use rustc_metadata::creader::CrateLoader; -use rustc_metadata::cstore::CStore; +use rustc_metadata::locator; use crate::registry::Registry; use std::borrow::ToOwned; @@ -25,7 +25,7 @@ pub struct PluginRegistrar { struct PluginLoader<'a> { sess: &'a Session, - reader: CrateLoader<'a>, + metadata_loader: &'a dyn MetadataLoader, plugins: Vec, } @@ -37,11 +37,10 @@ fn call_malformed_plugin_attribute(sess: &Session, span: Span) { /// Read plugin metadata and dynamically load registrar functions. pub fn load_plugins(sess: &Session, - cstore: &CStore, + metadata_loader: &dyn MetadataLoader, krate: &ast::Crate, - crate_name: &str, addl_plugins: Option>) -> Vec { - let mut loader = PluginLoader::new(sess, cstore, crate_name); + let mut loader = PluginLoader { sess, metadata_loader, plugins: Vec::new() }; // do not report any error now. since crate attributes are // not touched by expansion, every use of plugin without @@ -80,16 +79,8 @@ pub fn load_plugins(sess: &Session, } impl<'a> PluginLoader<'a> { - fn new(sess: &'a Session, cstore: &'a CStore, crate_name: &str) -> Self { - PluginLoader { - sess, - reader: CrateLoader::new(sess, cstore, crate_name), - plugins: vec![], - } - } - fn load_plugin(&mut self, span: Span, name: Symbol, args: Vec) { - let registrar = self.reader.find_plugin_registrar(span, name); + let registrar = locator::find_plugin_registrar(self.sess, self.metadata_loader, span, name); if let Some((lib, disambiguator)) = registrar { let symbol = self.sess.generate_plugin_registrar_symbol(disambiguator); diff --git a/src/librustc_plugin/registry.rs b/src/librustc_plugin/registry.rs index b826dd911983..2e23b8c870cf 100644 --- a/src/librustc_plugin/registry.rs +++ b/src/librustc_plugin/registry.rs @@ -1,8 +1,7 @@ //! Used by plugin crates to tell `rustc` about the plugins they provide. -use rustc::lint::{EarlyLintPassObject, LateLintPassObject, LintId, Lint}; +use rustc::lint::LintStore; use rustc::session::Session; -use rustc::util::nodemap::FxHashMap; use syntax_expand::base::{SyntaxExtension, SyntaxExtensionKind, NamedSyntaxExtension}; use syntax_expand::base::MacroExpanderFn; @@ -26,6 +25,9 @@ pub struct Registry<'a> { /// from the plugin registrar. pub sess: &'a Session, + /// The `LintStore` allows plugins to register new lints. + pub lint_store: &'a mut LintStore, + #[doc(hidden)] pub args_hidden: Option>, @@ -35,15 +37,6 @@ pub struct Registry<'a> { #[doc(hidden)] pub syntax_exts: Vec, - #[doc(hidden)] - pub early_lint_passes: Vec, - - #[doc(hidden)] - pub late_lint_passes: Vec, - - #[doc(hidden)] - pub lint_groups: FxHashMap<&'static str, (Vec, Option<&'static str>)>, - #[doc(hidden)] pub llvm_passes: Vec, @@ -53,15 +46,13 @@ pub struct Registry<'a> { impl<'a> Registry<'a> { #[doc(hidden)] - pub fn new(sess: &'a Session, krate_span: Span) -> Registry<'a> { + pub fn new(sess: &'a Session, lint_store: &'a mut LintStore, krate_span: Span) -> Registry<'a> { Registry { sess, + lint_store, args_hidden: None, krate_span, syntax_exts: vec![], - early_lint_passes: vec![], - late_lint_passes: vec![], - lint_groups: FxHashMap::default(), llvm_passes: vec![], attributes: vec![], } @@ -99,27 +90,6 @@ impl<'a> Registry<'a> { self.register_syntax_extension(Symbol::intern(name), ext); } - /// Register a compiler lint pass. - pub fn register_early_lint_pass(&mut self, lint_pass: EarlyLintPassObject) { - self.early_lint_passes.push(lint_pass); - } - - /// Register a compiler lint pass. - pub fn register_late_lint_pass(&mut self, lint_pass: LateLintPassObject) { - self.late_lint_passes.push(lint_pass); - } - /// Register a lint group. - pub fn register_lint_group( - &mut self, - name: &'static str, - deprecated_name: Option<&'static str>, - to: Vec<&'static Lint> - ) { - self.lint_groups.insert(name, - (to.into_iter().map(|x| LintId::of(x)).collect(), - deprecated_name)); - } - /// Register an LLVM pass. /// /// Registration with LLVM itself is handled through static C++ objects with diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index e261d3af61ff..c0fb8e33a819 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -110,14 +110,14 @@ impl<'a> Resolver<'a> { } let (name, parent) = if def_id.index == CRATE_DEF_INDEX { - (self.cstore.crate_name_untracked(def_id.krate).as_interned_str(), None) + (self.cstore().crate_name_untracked(def_id.krate), None) } else { - let def_key = self.cstore.def_key(def_id); + let def_key = self.cstore().def_key(def_id); (def_key.disambiguated_data.data.get_opt_name().unwrap(), Some(self.get_module(DefId { index: def_key.parent.unwrap(), ..def_id }))) }; - let kind = ModuleKind::Def(DefKind::Mod, def_id, name.as_symbol()); + let kind = ModuleKind::Def(DefKind::Mod, def_id, name); let module = self.arenas.alloc_module(ModuleData::new( parent, kind, def_id, ExpnId::root(), DUMMY_SP )); @@ -153,9 +153,8 @@ impl<'a> Resolver<'a> { return Some(ext.clone()); } - let ext = Lrc::new(match self.cstore.load_macro_untracked(def_id, &self.session) { - LoadedMacro::MacroDef(item) => - self.compile_macro(&item, self.cstore.crate_edition_untracked(def_id.krate)), + let ext = Lrc::new(match self.cstore().load_macro_untracked(def_id, &self.session) { + LoadedMacro::MacroDef(item, edition) => self.compile_macro(&item, edition), LoadedMacro::ProcMacro(ext) => ext, }); @@ -177,7 +176,7 @@ impl<'a> Resolver<'a> { crate fn build_reduced_graph_external(&mut self, module: Module<'a>) { let def_id = module.def_id().expect("unpopulated module without a def-id"); - for child in self.cstore.item_children_untracked(def_id, self.session) { + for child in self.cstore().item_children_untracked(def_id, self.session) { let child = child.map_id(|_| panic!("unexpected id")); BuildReducedGraphVisitor { r: self, parent_scope: ParentScope::module(module) } .build_reduced_graph_for_external_crate_res(child); @@ -885,19 +884,19 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { bug!("unexpected resolution: {:?}", res) } // Record some extra data for better diagnostics. + let cstore = self.r.cstore(); match res { Res::Def(DefKind::Struct, def_id) | Res::Def(DefKind::Union, def_id) => { - let field_names = - self.r.cstore.struct_field_names_untracked(def_id, self.r.session); + let field_names = cstore.struct_field_names_untracked(def_id, self.r.session); self.insert_field_names(def_id, field_names); } Res::Def(DefKind::Method, def_id) => { - if self.r.cstore.associated_item_cloned_untracked(def_id).method_has_self_argument { + if cstore.associated_item_cloned_untracked(def_id).method_has_self_argument { self.r.has_self.insert(def_id); } } Res::Def(DefKind::Ctor(CtorOf::Struct, ..), def_id) => { - let parent = self.r.cstore.def_key(def_id).parent; + let parent = cstore.def_key(def_id).parent; if let Some(struct_def_id) = parent.map(|index| DefId { index, ..def_id }) { self.r.struct_constructors.insert(struct_def_id, (res, vis)); } diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 5647d5b2794a..7634093fbefb 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -367,16 +367,6 @@ impl<'a> Resolver<'a> { span, "`Self` in type parameter default".to_string()); err } - ResolutionError::ConstParamDependentOnTypeParam => { - let mut err = struct_span_err!( - self.session, - span, - E0671, - "const parameters cannot depend on type parameters" - ); - err.span_label(span, format!("const parameter depends on type parameter")); - err - } } } diff --git a/src/librustc_resolve/error_codes.rs b/src/librustc_resolve/error_codes.rs index b82cba8c83dc..9883a64a1e89 100644 --- a/src/librustc_resolve/error_codes.rs +++ b/src/librustc_resolve/error_codes.rs @@ -1831,7 +1831,7 @@ An item usage is ambiguous. Erroneous code example: -```compile_fail,E0659 +```compile_fail,edition2018,E0659 pub mod moon { pub fn foo() {} } @@ -1841,12 +1841,12 @@ pub mod earth { } mod collider { - pub use moon::*; - pub use earth::*; + pub use crate::moon::*; + pub use crate::earth::*; } fn main() { - collider::foo(); // ERROR: `foo` is ambiguous + crate::collider::foo(); // ERROR: `foo` is ambiguous } ``` @@ -1858,7 +1858,7 @@ functions collide. To solve this error, the best solution is generally to keep the path before the item when using it. Example: -``` +```edition2018 pub mod moon { pub fn foo() {} } @@ -1868,25 +1868,26 @@ pub mod earth { } mod collider { - pub use moon; - pub use earth; + pub use crate::moon; + pub use crate::earth; } fn main() { - collider::moon::foo(); // ok! - collider::earth::foo(); // ok! + crate::collider::moon::foo(); // ok! + crate::collider::earth::foo(); // ok! } ``` "##, E0671: r##" +#### Note: this error code is no longer emitted by the compiler. + Const parameters cannot depend on type parameters. The following is therefore invalid: -```compile_fail,E0671 +```compile_fail,E0741 #![feature(const_generics)] -fn const_id() -> T { // error: const parameter - // depends on type parameter +fn const_id() -> T { // error N } ``` diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index 73a282b1a0ec..136ab1f0444f 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -111,9 +111,6 @@ crate enum RibKind<'a> { /// from the default of a type parameter because they're not declared /// before said type parameter. Also see the `visit_generics` override. ForwardTyParamBanRibKind, - - /// We forbid the use of type parameters as the types of const parameters. - TyParamAsConstParamTy, } impl RibKind<'_> { @@ -128,8 +125,7 @@ impl RibKind<'_> { | MacroDefinition(_) => false, AssocItemRibKind | ItemRibKind(_) - | ForwardTyParamBanRibKind - | TyParamAsConstParamTy => true, + | ForwardTyParamBanRibKind => true, } } } @@ -483,18 +479,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LateResolutionVisitor<'a, '_> { default_ban_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), Res::Err); } - // We also ban access to type parameters for use as the types of const parameters. - let mut const_ty_param_ban_rib = Rib::new(TyParamAsConstParamTy); - const_ty_param_ban_rib.bindings.extend(generics.params.iter() - .filter(|param| { - if let GenericParamKind::Type { .. } = param.kind { - true - } else { - false - } - }) - .map(|param| (Ident::with_dummy_span(param.ident.name), Res::Err))); - for param in &generics.params { match param.kind { GenericParamKind::Lifetime { .. } => self.visit_generic_param(param), @@ -513,15 +497,10 @@ impl<'a, 'tcx> Visitor<'tcx> for LateResolutionVisitor<'a, '_> { default_ban_rib.bindings.remove(&Ident::with_dummy_span(param.ident.name)); } GenericParamKind::Const { ref ty } => { - self.ribs[TypeNS].push(const_ty_param_ban_rib); - for bound in ¶m.bounds { self.visit_param_bound(bound); } - self.visit_ty(ty); - - const_ty_param_ban_rib = self.ribs[TypeNS].pop().unwrap(); } } } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 17d8f0f211a9..923928063472 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -21,14 +21,14 @@ use Determinacy::*; use rustc::hir::map::Definitions; use rustc::hir::{self, PrimTy, Bool, Char, Float, Int, Uint, Str}; -use rustc::middle::cstore::CrateStore; +use rustc::middle::cstore::{CrateStore, MetadataLoaderDyn}; use rustc::session::Session; use rustc::lint; use rustc::hir::def::{self, DefKind, PartialRes, CtorKind, CtorOf, NonMacroAttrKind, ExportMap}; use rustc::hir::def::Namespace::*; use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, CrateNum, DefId}; use rustc::hir::{TraitMap, GlobMap}; -use rustc::ty::{self, DefIdTree}; +use rustc::ty::{self, DefIdTree, ResolverOutputs}; use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet, DefIdMap}; use rustc::span_bug; @@ -215,8 +215,6 @@ enum ResolutionError<'a> { ForwardDeclaredTyParam, // FIXME(const_generics:defaults) /// Error E0735: type parameters with a default cannot use `Self` SelfInTyParamDefault, - /// Error E0671: const parameter cannot depend on type parameter. - ConstParamDependentOnTypeParam, } // A minimal representation of a path segment. We use this in resolve because @@ -829,14 +827,13 @@ pub struct ExternPreludeEntry<'a> { /// This is the visitor that walks the whole crate. pub struct Resolver<'a> { session: &'a Session, - cstore: &'a CStore, - pub definitions: Definitions, + definitions: Definitions, - pub graph_root: Module<'a>, + graph_root: Module<'a>, prelude: Option>, - pub extern_prelude: FxHashMap>, + extern_prelude: FxHashMap>, /// N.B., this is used only for better diagnostics, not name resolution itself. has_self: FxHashSet, @@ -869,9 +866,9 @@ pub struct Resolver<'a> { label_res_map: NodeMap, /// `CrateNum` resolutions of `extern crate` items. - pub extern_crate_map: NodeMap, - pub export_map: ExportMap, - pub trait_map: TraitMap, + extern_crate_map: NodeMap, + export_map: ExportMap, + trait_map: TraitMap, /// A map from nodes to anonymous modules. /// Anonymous modules are pseudo-modules that are implicitly created around items @@ -898,11 +895,11 @@ pub struct Resolver<'a> { underscore_disambiguator: u32, /// Maps glob imports to the names of items actually imported. - pub glob_map: GlobMap, + glob_map: GlobMap, used_imports: FxHashSet<(NodeId, Namespace)>, - pub maybe_unused_trait_imports: NodeSet, - pub maybe_unused_extern_crates: Vec<(NodeId, Span)>, + maybe_unused_trait_imports: NodeSet, + maybe_unused_extern_crates: Vec<(NodeId, Span)>, /// Privacy errors are delayed until the end in order to deduplicate them. privacy_errors: Vec>, @@ -916,11 +913,11 @@ pub struct Resolver<'a> { arenas: &'a ResolverArenas<'a>, dummy_binding: &'a NameBinding<'a>, - crate_loader: &'a CrateLoader<'a>, + crate_loader: CrateLoader<'a>, macro_names: FxHashSet, builtin_macros: FxHashMap, macro_use_prelude: FxHashMap>, - pub all_macros: FxHashMap, + all_macros: FxHashMap, macro_map: FxHashMap>, dummy_ext_bang: Lrc, dummy_ext_derive: Lrc, @@ -1015,7 +1012,7 @@ impl<'a, 'b> DefIdTree for &'a Resolver<'b> { fn parent(self, id: DefId) -> Option { match id.krate { LOCAL_CRATE => self.definitions.def_key(id.index).parent, - _ => self.cstore.def_key(id).parent, + _ => self.cstore().def_key(id).parent, }.map(|index| DefId { index, ..id }) } } @@ -1023,6 +1020,10 @@ impl<'a, 'b> DefIdTree for &'a Resolver<'b> { /// This interface is used through the AST→HIR step, to embed full paths into the HIR. After that /// the resolver is no longer needed as all the relevant information is inline. impl<'a> hir::lowering::Resolver for Resolver<'a> { + fn cstore(&self) -> &dyn CrateStore { + self.cstore() + } + fn resolve_str_path( &mut self, span: Span, @@ -1083,10 +1084,9 @@ impl<'a> hir::lowering::Resolver for Resolver<'a> { impl<'a> Resolver<'a> { pub fn new(session: &'a Session, - cstore: &'a CStore, krate: &Crate, crate_name: &str, - crate_loader: &'a CrateLoader<'a>, + metadata_loader: &'a MetadataLoaderDyn, arenas: &'a ResolverArenas<'a>) -> Resolver<'a> { let root_def_id = DefId::local(CRATE_DEF_INDEX); @@ -1147,8 +1147,6 @@ impl<'a> Resolver<'a> { Resolver { session, - cstore, - definitions, // The outermost module has def ID 0; this is not reflected in the @@ -1202,7 +1200,7 @@ impl<'a> Resolver<'a> { vis: ty::Visibility::Public, }), - crate_loader, + crate_loader: CrateLoader::new(session, metadata_loader, crate_name), macro_names: FxHashSet::default(), builtin_macros: Default::default(), macro_use_prelude: FxHashMap::default(), @@ -1236,6 +1234,42 @@ impl<'a> Resolver<'a> { Default::default() } + pub fn into_outputs(self) -> ResolverOutputs { + ResolverOutputs { + definitions: self.definitions, + cstore: Box::new(self.crate_loader.into_cstore()), + extern_crate_map: self.extern_crate_map, + export_map: self.export_map, + trait_map: self.trait_map, + glob_map: self.glob_map, + maybe_unused_trait_imports: self.maybe_unused_trait_imports, + maybe_unused_extern_crates: self.maybe_unused_extern_crates, + extern_prelude: self.extern_prelude.iter().map(|(ident, entry)| { + (ident.name, entry.introduced_by_item) + }).collect(), + } + } + + pub fn clone_outputs(&self) -> ResolverOutputs { + ResolverOutputs { + definitions: self.definitions.clone(), + cstore: Box::new(self.cstore().clone()), + extern_crate_map: self.extern_crate_map.clone(), + export_map: self.export_map.clone(), + trait_map: self.trait_map.clone(), + glob_map: self.glob_map.clone(), + maybe_unused_trait_imports: self.maybe_unused_trait_imports.clone(), + maybe_unused_extern_crates: self.maybe_unused_extern_crates.clone(), + extern_prelude: self.extern_prelude.iter().map(|(ident, entry)| { + (ident.name, entry.introduced_by_item) + }).collect(), + } + } + + pub fn cstore(&self) -> &CStore { + self.crate_loader.cstore() + } + fn non_macro_attr(&self, mark_used: bool) -> Lrc { self.non_macro_attrs[mark_used as usize].clone() } @@ -2169,15 +2203,6 @@ impl<'a> Resolver<'a> { return Res::Err; } - // An invalid use of a type parameter as the type of a const parameter. - if let TyParamAsConstParamTy = all_ribs[rib_index].kind { - if record_used { - self.report_error(span, ResolutionError::ConstParamDependentOnTypeParam); - } - assert_eq!(res, Res::Err); - return Res::Err; - } - match res { Res::Local(_) => { use ResolutionError::*; @@ -2186,7 +2211,7 @@ impl<'a> Resolver<'a> { for rib in ribs { match rib.kind { NormalRibKind | ModuleRibKind(..) | MacroDefinition(..) | - ForwardTyParamBanRibKind | TyParamAsConstParamTy => { + ForwardTyParamBanRibKind => { // Nothing to do. Continue. } ItemRibKind(_) | FnItemRibKind | AssocItemRibKind => { @@ -2220,7 +2245,7 @@ impl<'a> Resolver<'a> { let has_generic_params = match rib.kind { NormalRibKind | AssocItemRibKind | ModuleRibKind(..) | MacroDefinition(..) | ForwardTyParamBanRibKind | - ConstantItemRibKind | TyParamAsConstParamTy => { + ConstantItemRibKind => { // Nothing to do. Continue. continue; } @@ -2808,6 +2833,16 @@ impl<'a> Resolver<'a> { seg.id = self.session.next_node_id(); seg } + + // For rustdoc. + pub fn graph_root(&self) -> Module<'a> { + self.graph_root + } + + // For rustdoc. + pub fn all_macros(&self) -> &FxHashMap { + &self.all_macros + } } fn names_to_string(names: &[Name]) -> String { diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 34edd5eaf4fc..31340ddd6837 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -1344,7 +1344,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { if res != Res::Err { if let Some(def_id) = res.opt_def_id() { if !def_id.is_local() { - this.cstore.export_macros_untracked(def_id.krate); + this.cstore().export_macros_untracked(def_id.krate); } } reexports.push(Export { diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 8eab9c4e67e3..79dc4f7e1361 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -131,7 +131,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { { let tcx = self.tcx(); let lifetime_name = |def_id| { - tcx.hir().name(tcx.hir().as_local_hir_id(def_id).unwrap()).as_interned_str() + tcx.hir().name(tcx.hir().as_local_hir_id(def_id).unwrap()) }; let r = match tcx.named_region(lifetime.hir_id) { @@ -1274,8 +1274,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { span, item.trait_ref().def_id(), object_safety_violations - ) - .map(|mut err| err.emit()); + ).emit(); return tcx.types.err; } } @@ -2023,7 +2022,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let item_def_id = tcx.hir().local_def_id(item_id); let generics = tcx.generics_of(item_def_id); let index = generics.param_def_id_to_index[&def_id]; - tcx.mk_ty_param(index, tcx.hir().name(hir_id).as_interned_str()) + tcx.mk_ty_param(index, tcx.hir().name(hir_id)) } Res::SelfTy(Some(_), None) => { // `Self` in trait or type alias. @@ -2204,7 +2203,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let item_def_id = tcx.hir().local_def_id(item_id); let generics = tcx.generics_of(item_def_id); let index = generics.param_def_id_to_index[&tcx.hir().local_def_id(hir_id)]; - let name = tcx.hir().name(hir_id).as_interned_str(); + let name = tcx.hir().name(hir_id); const_.val = ConstValue::Param(ty::ParamConst::new(index, name)); } diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index dfeb5fb958cd..9cbde276ae97 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -428,21 +428,36 @@ impl<'a, 'tcx> CastCheck<'tcx> { self.report_cast_to_unsized_type(fcx); } else if self.expr_ty.references_error() || self.cast_ty.references_error() { // No sense in giving duplicate error messages - } else if self.try_coercion_cast(fcx) { - self.trivial_cast_lint(fcx); - debug!(" -> CoercionCast"); - fcx.tables.borrow_mut().set_coercion_cast(self.expr.hir_id.local_id); - } else { - match self.do_check(fcx) { - Ok(k) => { - debug!(" -> {:?}", k); + match self.try_coercion_cast(fcx) { + Ok(()) => { + self.trivial_cast_lint(fcx); + debug!(" -> CoercionCast"); + fcx.tables.borrow_mut() + .set_coercion_cast(self.expr.hir_id.local_id); + } + Err(ty::error::TypeError::ObjectUnsafeCoercion(did)) => { + self.report_object_unsafe_cast(&fcx, did); + } + Err(_) => { + match self.do_check(fcx) { + Ok(k) => { + debug!(" -> {:?}", k); + } + Err(e) => self.report_cast_error(fcx, e), + }; } - Err(e) => self.report_cast_error(fcx, e), }; } } + fn report_object_unsafe_cast(&self, fcx: &FnCtxt<'a, 'tcx>, did: DefId) { + let violations = fcx.tcx.object_safety_violations(did); + let mut err = fcx.tcx.report_object_safety_error(self.cast_span, did, violations); + err.note(&format!("required by cast to type '{}'", fcx.ty_to_string(self.cast_ty))); + err.emit(); + } + /// Checks a cast, and report an error if one exists. In some cases, this /// can return Ok and create type errors in the fcx rather than returning /// directly. coercion-cast is handled in check instead of here. @@ -646,8 +661,14 @@ impl<'a, 'tcx> CastCheck<'tcx> { } } - fn try_coercion_cast(&self, fcx: &FnCtxt<'a, 'tcx>) -> bool { - fcx.try_coerce(self.expr, self.expr_ty, self.cast_ty, AllowTwoPhase::No).is_ok() + fn try_coercion_cast( + &self, + fcx: &FnCtxt<'a, 'tcx>, + ) -> Result<(), ty::error::TypeError<'_>> { + match fcx.try_coerce(self.expr, self.expr_ty, self.cast_ty, AllowTwoPhase::No) { + Ok(_) => Ok(()), + Err(err) => Err(err), + } } } diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index bfccb032458f..f79351dc9031 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -61,10 +61,11 @@ use rustc::traits::{self, ObligationCause, ObligationCauseCode}; use rustc::ty::adjustment::{ Adjustment, Adjust, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCast }; -use rustc::ty::{self, TypeAndMut, Ty, subst::SubstsRef}; +use rustc::ty::{self, TypeAndMut, Ty}; use rustc::ty::fold::TypeFoldable; use rustc::ty::error::TypeError; use rustc::ty::relate::RelateResult; +use rustc::ty::subst::SubstsRef; use smallvec::{smallvec, SmallVec}; use std::ops::Deref; use syntax::feature_gate; @@ -196,9 +197,16 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // a "spurious" type variable, and we don't want to have that // type variable in memory if the coercion fails. let unsize = self.commit_if_ok(|_| self.coerce_unsized(a, b)); - if unsize.is_ok() { - debug!("coerce: unsize successful"); - return unsize; + match unsize { + Ok(_) => { + debug!("coerce: unsize successful"); + return unsize; + } + Err(TypeError::ObjectUnsafeCoercion(did)) => { + debug!("coerce: unsize not object safe"); + return Err(TypeError::ObjectUnsafeCoercion(did)); + } + Err(_) => {} } debug!("coerce: unsize failed"); @@ -539,7 +547,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { let mut selcx = traits::SelectionContext::new(self); // Create an obligation for `Source: CoerceUnsized`. - let cause = ObligationCause::misc(self.cause.span, self.body_id); + let cause = ObligationCause::new( + self.cause.span, + self.body_id, + ObligationCauseCode::Coercion { source, target }, + ); // Use a FIFO queue for this custom fulfillment procedure. // @@ -566,14 +578,15 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { let obligation = queue.remove(0); debug!("coerce_unsized resolve step: {:?}", obligation); let trait_ref = match obligation.predicate { - ty::Predicate::Trait(ref t) if traits.contains(&t.def_id()) => { - if unsize_did == t.def_id() { - if let ty::Tuple(..) = &t.skip_binder().input_types().nth(1).unwrap().kind { + ty::Predicate::Trait(ref tr) if traits.contains(&tr.def_id()) => { + if unsize_did == tr.def_id() { + let sty = &tr.skip_binder().input_types().nth(1).unwrap().kind; + if let ty::Tuple(..) = sty { debug!("coerce_unsized: found unsized tuple coercion"); has_unsized_tuple_coercion = true; } } - t.clone() + tr.clone() } _ => { coercion.obligations.push(obligation); diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index f5f85bbcb100..8668dd99a8cf 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -566,7 +566,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // the `enclosing_loops` field and let's coerce the // type of `expr_opt` into what is expected. let mut enclosing_breakables = self.enclosing_breakables.borrow_mut(); - let ctxt = enclosing_breakables.find_breakable(target_id); + let ctxt = match enclosing_breakables.opt_find_breakable(target_id) { + Some(ctxt) => ctxt, + None => { // Avoid ICE when `break` is inside a closure (#65383). + self.tcx.sess.delay_span_bug( + expr.span, + "break was outside loop, but no error was emitted", + ); + return tcx.types.err; + } + }; + if let Some(ref mut coerce) = ctxt.coerce { if let Some(ref e) = expr_opt { coerce.coerce(self, &cause, e, e_ty); @@ -592,7 +602,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } else { // If `ctxt.coerce` is `None`, we can just ignore - // the type of the expresison. This is because + // the type of the expression. This is because // either this was a break *without* a value, in // which case it is always a legal type (`()`), or // else an error would have been flagged by the diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index aeb2c40e2ef8..72a0fe887b96 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -7,7 +7,7 @@ use rustc::ty::subst::Subst; use crate::require_same_types; use rustc_target::spec::abi::Abi; -use syntax::symbol::InternedString; +use syntax::symbol::Symbol; use rustc::hir; @@ -80,7 +80,7 @@ pub fn intrinsic_operation_unsafety(intrinsic: &str) -> hir::Unsafety { /// Remember to add all intrinsics here, in librustc_codegen_llvm/intrinsic.rs, /// and in libcore/intrinsics.rs pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem) { - let param = |n| tcx.mk_ty_param(n, InternedString::intern(&format!("P{}", n))); + let param = |n| tcx.mk_ty_param(n, Symbol::intern(&format!("P{}", n))); let name = it.ident.as_str(); let mk_va_list_ty = |mutbl| { @@ -387,7 +387,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem) { /// Type-check `extern "platform-intrinsic" { ... }` functions. pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem) { let param = |n| { - let name = InternedString::intern(&format!("P{}", n)); + let name = Symbol::intern(&format!("P{}", n)); tcx.mk_ty_param(n, name) }; diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 9baf06be3f6b..59636d32bc03 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -141,14 +141,24 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { /////////////////////////////////////////////////////////////////////////// // ADJUSTMENTS - fn adjust_self_ty(&mut self, - unadjusted_self_ty: Ty<'tcx>, - pick: &probe::Pick<'tcx>) - -> Ty<'tcx> { + fn adjust_self_ty( + &mut self, + unadjusted_self_ty: Ty<'tcx>, + pick: &probe::Pick<'tcx>, + ) -> Ty<'tcx> { // Commit the autoderefs by calling `autoderef` again, but this // time writing the results into the various tables. let mut autoderef = self.autoderef(self.span, unadjusted_self_ty); - let (_, n) = autoderef.nth(pick.autoderefs).unwrap(); + let (_, n) = match autoderef.nth(pick.autoderefs) { + Some(n) => n, + None => { + self.tcx.sess.delay_span_bug( + syntax_pos::DUMMY_SP, + &format!("failed autoderef {}", pick.autoderefs), + ); + return self.tcx.types.err; + } + }; assert_eq!(n, pick.autoderefs); let mut adjustments = autoderef.adjust_steps(self, Needs::None); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 73a025182a7e..96a097695fa1 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -536,10 +536,16 @@ pub struct EnclosingBreakables<'tcx> { impl<'tcx> EnclosingBreakables<'tcx> { fn find_breakable(&mut self, target_id: hir::HirId) -> &mut BreakableCtxt<'tcx> { - let ix = *self.by_id.get(&target_id).unwrap_or_else(|| { + self.opt_find_breakable(target_id).unwrap_or_else(|| { bug!("could not find enclosing breakable with id {}", target_id); - }); - &mut self.stack[ix] + }) + } + + fn opt_find_breakable(&mut self, target_id: hir::HirId) -> Option<&mut BreakableCtxt<'tcx>> { + match self.by_id.get(&target_id) { + Some(ix) => Some(&mut self.stack[*ix]), + None => None, + } } } @@ -2761,8 +2767,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut opaque_types = self.opaque_types.borrow_mut(); for (ty, decl) in opaque_type_map { - let old_value = opaque_types.insert(ty, decl); - assert!(old_value.is_none(), "instantiated twice: {:?}/{:?}", ty, decl); + let _ = opaque_types.insert(ty, decl); } value diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index a44c475e0f8a..8adf4bb94a89 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -183,8 +183,11 @@ fn check_impl_overlap<'tcx>(tcx: TyCtxt<'tcx>, hir_id: HirId) { for component_def_id in component_def_ids { if !tcx.is_object_safe(component_def_id) { - // This is an error, but it will be reported by wfcheck. Ignore it here. + // Without the 'object_safe_for_dispatch' feature this is an error + // which will be reported by wfcheck. Ignore it here. // This is tested by `coherence-impl-trait-for-trait-object-safe.rs`. + // With the feature enabled, the trait is not implemented automatically, + // so this is valid. } else { let mut supertrait_def_ids = traits::supertrait_def_ids(tcx, component_def_id); diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 1749fd1075e0..00435d67184a 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -36,7 +36,7 @@ use syntax::ast; use syntax::ast::{Ident, MetaItemKind}; use syntax::attr::{InlineAttr, OptimizeAttr, list_contains_name, mark_used}; use syntax::feature_gate; -use syntax::symbol::{InternedString, kw, Symbol, sym}; +use syntax::symbol::{kw, Symbol, sym}; use syntax_pos::{Span, DUMMY_SP}; use rustc::hir::def::{CtorKind, Res, DefKind}; @@ -265,7 +265,7 @@ fn type_param_predicates( let param_owner_def_id = tcx.hir().local_def_id(param_owner); let generics = tcx.generics_of(param_owner_def_id); let index = generics.param_def_id_to_index[&def_id]; - let ty = tcx.mk_ty_param(index, tcx.hir().ty_param_name(param_id).as_interned_str()); + let ty = tcx.mk_ty_param(index, tcx.hir().ty_param_name(param_id)); // Don't look for bounds where the type parameter isn't in scope. let parent = if item_def_id == param_owner_def_id { @@ -961,7 +961,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics { opt_self = Some(ty::GenericParamDef { index: 0, - name: kw::SelfUpper.as_interned_str(), + name: kw::SelfUpper, def_id: tcx.hir().local_def_id(param_id), pure_wrt_drop: false, kind: ty::GenericParamDefKind::Type { @@ -1006,7 +1006,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics { early_lifetimes .enumerate() .map(|(i, param)| ty::GenericParamDef { - name: param.name.ident().as_interned_str(), + name: param.name.ident().name, index: own_start + i as u32, def_id: tcx.hir().local_def_id(param.hir_id), pure_wrt_drop: param.pure_wrt_drop, @@ -1060,7 +1060,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics { let param_def = ty::GenericParamDef { index: type_start + i as u32, - name: param.name.ident().as_interned_str(), + name: param.name.ident().name, def_id: tcx.hir().local_def_id(param.hir_id), pure_wrt_drop: param.pure_wrt_drop, kind, @@ -1090,7 +1090,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics { .enumerate() .map(|(i, &arg)| ty::GenericParamDef { index: type_start + i as u32, - name: InternedString::intern(arg), + name: Symbol::intern(arg), def_id, pure_wrt_drop: false, kind: ty::GenericParamDefKind::Type { @@ -1105,7 +1105,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics { params.extend(upvars.iter().zip((dummy_args.len() as u32)..).map(|(_, i)| { ty::GenericParamDef { index: type_start + i, - name: InternedString::intern(""), + name: Symbol::intern(""), def_id, pure_wrt_drop: false, kind: ty::GenericParamDefKind::Type { @@ -1532,6 +1532,17 @@ pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option { @@ -2198,7 +2209,7 @@ fn explicit_predicates_of( let region = tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion { def_id: tcx.hir().local_def_id(param.hir_id), index, - name: param.name.ident().as_interned_str(), + name: param.name.ident().name, })); index += 1; @@ -2221,7 +2232,7 @@ fn explicit_predicates_of( // type parameter (e.g., ``). for param in &ast_generics.params { if let GenericParamKind::Type { .. } = param.kind { - let name = param.name.ident().as_interned_str(); + let name = param.name.ident().name; let param_ty = ty::ParamTy::new(index, name).to_ty(tcx); index += 1; diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs index 3ecbf620cbc7..75b508a1bbf0 100644 --- a/src/librustc_typeck/error_codes.rs +++ b/src/librustc_typeck/error_codes.rs @@ -194,7 +194,7 @@ a guard. ```compile_fail,E0029 let string = "salutations !"; -// The ordering relation for strings can't be evaluated at compile time, +// The ordering relation for strings cannot be evaluated at compile time, // so this doesn't work: match string { "hello" ..= "world" => {} @@ -348,7 +348,7 @@ fn main() { "##, E0044: r##" -You can't use type or const parameters on foreign items. +You cannot use type or const parameters on foreign items. Example of erroneous code: ```compile_fail,E0044 @@ -788,7 +788,7 @@ fn some_other_func() {} fn some_function() { SOME_CONST = 14; // error : a constant value cannot be changed! 1 = 3; // error : 1 isn't a valid place! - some_other_func() = 4; // error : we can't assign value to a function! + some_other_func() = 4; // error : we cannot assign value to a function! SomeStruct.x = 12; // error : SomeStruct a structure name but it is used // like a variable! } @@ -3891,6 +3891,33 @@ details. [issue #33685]: https://github.com/rust-lang/rust/issues/33685 "##, +E0588: r##" +A type with `packed` representation hint has a field with `align` +representation hint. + +Erroneous code example: + +```compile_fail,E0588 +#[repr(align(16))] +struct Aligned(i32); + +#[repr(packed)] // error! +struct Packed(Aligned); +``` + +Just like you cannot have both `align` and `packed` representation hints on a +same type, a `packed` type cannot contain another type with the `align` +representation hint. However, you can do the opposite: + +``` +#[repr(packed)] +struct Packed(i32); + +#[repr(align(16))] // ok! +struct Aligned(Packed); +``` +"##, + E0592: r##" This error occurs when you defined methods or associated functions with same name. @@ -4299,7 +4326,7 @@ extern { unsafe { printf(::std::ptr::null(), 0f32); - // error: can't pass an `f32` to variadic function, cast to `c_double` + // error: cannot pass an `f32` to variadic function, cast to `c_double` } ``` @@ -4978,6 +5005,30 @@ the future, [RFC 2091] prohibits their implementation without a follow-up RFC. [RFC 2091]: https://github.com/rust-lang/rfcs/blob/master/text/2091-inline-semantic.md "##, +E0741: r##" +Only `structural_match` types (that is, types that derive `PartialEq` and `Eq`) +may be used as the types of const generic parameters. + +```compile_fail,E0741 +#![feature(const_generics)] + +struct A; + +struct B; // error! +``` + +To fix this example, we derive `PartialEq` and `Eq`. + +``` +#![feature(const_generics)] + +#[derive(PartialEq, Eq)] +struct A; + +struct B; // ok! +``` +"##, + ; // E0035, merged into E0087/E0089 // E0036, merged into E0087/E0089 @@ -5000,7 +5051,7 @@ the future, [RFC 2091] prohibits their implementation without a follow-up RFC. // E0174, // E0182, // merged into E0229 E0183, -// E0187, // can't infer the kind of the closure +// E0187, // cannot infer the kind of the closure // E0188, // can not cast an immutable reference to a mutable pointer // E0189, // deprecated: can only cast a boxed pointer to a boxed object // E0190, // deprecated: can only cast a &-pointer to an &-object @@ -5047,7 +5098,6 @@ the future, [RFC 2091] prohibits their implementation without a follow-up RFC. // E0564, // only named lifetimes are allowed in `impl Trait`, // but `{}` was found in the type `{}` E0587, // type has conflicting packed and align representation hints - E0588, // packed type cannot transitively contain a `[repr(align)]` type // E0611, // merged into E0616 // E0612, // merged into E0609 // E0613, // Removed (merged with E0609) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index e7cc8b76e485..a6a8fec429e2 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -479,8 +479,8 @@ fn build_static(cx: &DocContext<'_>, did: DefId, mutable: bool) -> clean::Static fn build_macro(cx: &DocContext<'_>, did: DefId, name: ast::Name) -> clean::ItemEnum { let imported_from = cx.tcx.original_crate_name(did.krate); - match cx.cstore.load_macro_untracked(did, cx.sess()) { - LoadedMacro::MacroDef(def) => { + match cx.enter_resolver(|r| r.cstore().load_macro_untracked(did, cx.sess())) { + LoadedMacro::MacroDef(def, _) => { let matchers: hir::HirVec = if let ast::ItemKind::MacroDef(ref def) = def.kind { let tts: Vec<_> = def.stream().into_trees().collect(); tts.chunks(4).map(|arm| arm[0].span()).collect() diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 09c9757dc4d0..abc8b8314494 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -31,7 +31,6 @@ use syntax::attr; use syntax_expand::base::MacroKind; use syntax::source_map::DUMMY_SP; use syntax::symbol::{Symbol, kw, sym}; -use syntax::symbol::InternedString; use syntax_pos::{self, Pos, FileName}; use std::collections::hash_map::Entry; @@ -1682,7 +1681,7 @@ impl<'a, 'tcx> Clean for (&'a ty::Generics, ty::GenericPredicates<'tcx .filter_map(|param| match param.kind { ty::GenericParamDefKind::Lifetime => None, ty::GenericParamDefKind::Type { synthetic, .. } => { - if param.name.as_symbol() == kw::SelfUpper { + if param.name == kw::SelfUpper { assert_eq!(param.index, 0); return None; } @@ -3701,13 +3700,6 @@ impl Clean for ast::Name { } } -impl Clean for InternedString { - #[inline] - fn clean(&self, _: &DocContext<'_>) -> String { - self.to_string() - } -} - #[derive(Clone, Debug)] pub struct Typedef { pub type_: Type, diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 2337ec5a52cc..b227f432a4e9 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -5,14 +5,13 @@ use rustc::hir::HirId; use rustc::middle::cstore::CrateStore; use rustc::middle::privacy::AccessLevels; use rustc::ty::{Ty, TyCtxt}; -use rustc::lint::{self, LintPass}; +use rustc::lint; use rustc::session::config::ErrorOutputType; use rustc::session::DiagnosticOutput; use rustc::util::nodemap::{FxHashMap, FxHashSet}; use rustc_interface::interface; use rustc_driver::abort_on_err; use rustc_resolve as resolve; -use rustc_metadata::cstore::CStore; use syntax::source_map; use syntax::attr; @@ -43,7 +42,6 @@ pub struct DocContext<'tcx> { pub tcx: TyCtxt<'tcx>, pub resolver: Rc>, - pub cstore: Lrc, /// Later on moved into `html::render::CACHE_KEY` pub renderinfo: RefCell, /// Later on moved through `clean::Crate` into `html::render::CACHE_KEY` @@ -117,9 +115,7 @@ impl<'tcx> DocContext<'tcx> { .def_path_table() .next_id() } else { - self.cstore - .def_path_table(crate_num) - .next_id() + self.enter_resolver(|r| r.cstore().def_path_table(crate_num).next_id()) }; DefId { @@ -273,10 +269,9 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt whitelisted_lints.extend(lint_opts.iter().map(|(lint, _)| lint).cloned()); let lints = || { - lint::builtin::HardwiredLints - .get_lints() + lint::builtin::HardwiredLints::get_lints() .into_iter() - .chain(rustc_lint::SoftLints.get_lints().into_iter()) + .chain(rustc_lint::SoftLints::get_lints().into_iter()) }; let lint_opts = lints().filter_map(|lint| { @@ -339,6 +334,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt stderr: None, crate_name, lint_caps, + register_lints: None, }; interface::run_compiler_in_existing_thread_pool(config, |compiler| { @@ -376,7 +372,6 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt let mut ctxt = DocContext { tcx, resolver, - cstore: compiler.cstore().clone(), external_traits: Default::default(), active_extern_traits: Default::default(), renderinfo: RefCell::new(renderinfo), diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index 0dc094ae329f..bbc00147ee14 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -59,7 +59,7 @@ impl Module<'hir> { fns : Vec::new(), mods : Vec::new(), typedefs : Vec::new(), - opaque_tys : Vec::new(), + opaque_tys : Vec::new(), statics : Vec::new(), constants : Vec::new(), traits : Vec::new(), diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 72a72e892814..414c3137376a 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1241,6 +1241,7 @@ fn settings(root_path: &str, suffix: &str) -> String { ("go-to-only-result", "Directly go to item in search if there is only one result", false), ("line-numbers", "Show line numbers on code examples", false), + ("disable-shortcuts", "Disable keyboard shortcuts", false), ]; format!( "

\ diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 17a940cc4c9f..f0104c9156de 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -79,6 +79,7 @@ function getSearchElement() { "derive", "traitalias"]; + var disableShortcuts = getCurrentValue("rustdoc-disable-shortcuts") !== "true"; var search_input = getSearchInput(); // On the search screen, so you remain on the last tab you opened. @@ -294,7 +295,7 @@ function getSearchElement() { function handleShortcut(ev) { // Don't interfere with browser shortcuts - if (ev.ctrlKey || ev.altKey || ev.metaKey) { + if (ev.ctrlKey || ev.altKey || ev.metaKey || disableShortcuts === true) { return; } diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 4270b162bafa..caa7f08f68cf 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -432,13 +432,13 @@ fn macro_resolve(cx: &DocContext<'_>, path_str: &str) -> Option { let path = ast::Path::from_ident(Ident::from_str(path_str)); cx.enter_resolver(|resolver| { if let Ok((Some(ext), res)) = resolver.resolve_macro_path( - &path, None, &ParentScope::module(resolver.graph_root), false, false + &path, None, &ParentScope::module(resolver.graph_root()), false, false ) { if let SyntaxExtensionKind::LegacyBang { .. } = ext.kind { return Some(res.map_id(|_| panic!("unexpected id"))); } } - if let Some(res) = resolver.all_macros.get(&Symbol::intern(path_str)) { + if let Some(res) = resolver.all_macros().get(&Symbol::intern(path_str)) { return Some(res.map_id(|_| panic!("unexpected id"))); } None diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 8afc50f83bfa..07dc1e4e9157 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -77,6 +77,7 @@ pub fn run(options: Options) -> i32 { stderr: None, crate_name: options.crate_name.clone(), lint_caps: Default::default(), + register_lints: None, }; let mut test_args = options.test_args.clone(); diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index 9bf5caf03636..c55911a33f52 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -23,7 +23,7 @@ libc = { version = "0.2.51", default-features = false, features = ['rustc-dep-of compiler_builtins = { version = "0.1.16" } profiler_builtins = { path = "../libprofiler_builtins", optional = true } unwind = { path = "../libunwind" } -hashbrown = { version = "0.6.1", default-features = false, features = ['rustc-dep-of-std'] } +hashbrown = { version = "0.6.2", default-features = false, features = ['rustc-dep-of-std'] } [dependencies.backtrace_rs] package = "backtrace" diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 93d3e4ea3df2..d0cb0104f6cb 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -276,6 +276,7 @@ #![feature(linkage)] #![feature(log_syntax)] #![feature(manually_drop_take)] +#![feature(matches_macro)] #![feature(maybe_uninit_ref)] #![feature(maybe_uninit_slice)] #![feature(needs_panic_runtime)] @@ -527,6 +528,7 @@ pub use core::{ writeln, // Unstable todo, + matches, }; // Re-export built-in macros defined through libcore. diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index 2dde81bb0ecd..619b18201908 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -217,7 +217,7 @@ pub fn update_panic_count(amt: isize) -> usize { PANIC_COUNT.with(|c| { let next = (c.get() as isize + amt) as usize; c.set(next); - return next + next }) } diff --git a/src/libstd/sys/unix/rand.rs b/src/libstd/sys/unix/rand.rs index c5be17633025..be112f6fc032 100644 --- a/src/libstd/sys/unix/rand.rs +++ b/src/libstd/sys/unix/rand.rs @@ -8,7 +8,7 @@ pub fn hashmap_random_keys() -> (u64, u64) { mem::size_of_val(&v)); imp::fill_bytes(view); } - return v + v } #[cfg(all(unix, diff --git a/src/libstd/sys/wasi/thread.rs b/src/libstd/sys/wasi/thread.rs index 28a504f19797..6ce41420284e 100644 --- a/src/libstd/sys/wasi/thread.rs +++ b/src/libstd/sys/wasi/thread.rs @@ -31,10 +31,10 @@ impl Thread { let nanos = dur.as_nanos(); assert!(nanos <= u64::max_value() as u128); - const CLOCK_ID: wasi::Userdata = 0x0123_45678; + const USERDATA: wasi::Userdata = 0x0123_45678; let clock = wasi::raw::__wasi_subscription_u_clock_t { - identifier: CLOCK_ID, + identifier: 0, clock_id: wasi::CLOCK_MONOTONIC, timeout: nanos as u64, precision: 0, @@ -42,7 +42,7 @@ impl Thread { }; let in_ = [wasi::Subscription { - userdata: 0, + userdata: USERDATA, type_: wasi::EVENTTYPE_CLOCK, u: wasi::raw::__wasi_subscription_u { clock: clock }, }]; @@ -53,7 +53,7 @@ impl Thread { }; match (res, event) { (Ok(1), wasi::Event { - userdata: CLOCK_ID, + userdata: USERDATA, error: 0, type_: wasi::EVENTTYPE_CLOCK, .. diff --git a/src/libstd/sys/windows/handle.rs b/src/libstd/sys/windows/handle.rs index 3e5aa6933546..3986cda1a504 100644 --- a/src/libstd/sys/windows/handle.rs +++ b/src/libstd/sys/windows/handle.rs @@ -46,7 +46,7 @@ impl Handle { pub fn into_raw(self) -> c::HANDLE { let ret = self.raw(); mem::forget(self); - return ret; + ret } } diff --git a/src/libstd/sys/windows/mutex.rs b/src/libstd/sys/windows/mutex.rs index 37cbdcefcedc..79dec1adf4bc 100644 --- a/src/libstd/sys/windows/mutex.rs +++ b/src/libstd/sys/windows/mutex.rs @@ -144,7 +144,7 @@ fn kind() -> Kind { Some(..) => Kind::SRWLock, }; KIND.store(ret as usize, Ordering::SeqCst); - return ret; + ret } pub struct ReentrantMutex { inner: UnsafeCell> } diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs index 8658deb85463..096b7bea8a5f 100644 --- a/src/libstd/sys/windows/process.rs +++ b/src/libstd/sys/windows/process.rs @@ -257,7 +257,7 @@ impl Stdio { let ret = io.duplicate(0, true, c::DUPLICATE_SAME_ACCESS); io.into_raw(); - return ret + ret } Err(..) => Ok(Handle::new(c::INVALID_HANDLE_VALUE)), } @@ -472,9 +472,8 @@ fn make_command_line(prog: &OsStr, args: &[OsString]) -> io::Result> { cmd.push('"' as u16); } - let mut iter = arg.encode_wide(); let mut backslashes: usize = 0; - while let Some(x) = iter.next() { + for x in arg.encode_wide() { if x == '\\' as u16 { backslashes += 1; } else { diff --git a/src/libstd/sys/windows/rand.rs b/src/libstd/sys/windows/rand.rs index c9bcb5d74151..993831bec188 100644 --- a/src/libstd/sys/windows/rand.rs +++ b/src/libstd/sys/windows/rand.rs @@ -13,7 +13,7 @@ pub fn hashmap_random_keys() -> (u64, u64) { panic!("couldn't generate random bytes: {}", io::Error::last_os_error()); } - return v + v } #[cfg(target_vendor = "uwp")] diff --git a/src/libstd/sys/windows/thread_local.rs b/src/libstd/sys/windows/thread_local.rs index 4c9734fa0aa6..728257cdd4bb 100644 --- a/src/libstd/sys/windows/thread_local.rs +++ b/src/libstd/sys/windows/thread_local.rs @@ -52,7 +52,7 @@ pub unsafe fn create(dtor: Option) -> Key { if let Some(f) = dtor { register_dtor(key, f); } - return key; + key } #[inline] diff --git a/src/libstd/sys/windows/time.rs b/src/libstd/sys/windows/time.rs index e0f0e3a1a45b..bd533c93d434 100644 --- a/src/libstd/sys/windows/time.rs +++ b/src/libstd/sys/windows/time.rs @@ -80,7 +80,7 @@ impl SystemTime { unsafe { let mut t: SystemTime = mem::zeroed(); c::GetSystemTimeAsFileTime(&mut t.t); - return t + t } } @@ -228,7 +228,7 @@ mod perf_counter { FREQUENCY = frequency; STATE.store(2, SeqCst); } - return frequency; + frequency } } diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs index e92c0d1c58e4..cfaab4e22e9c 100644 --- a/src/libstd/thread/local.rs +++ b/src/libstd/thread/local.rs @@ -509,9 +509,8 @@ pub mod os { pub unsafe fn get(&'static self, init: fn() -> T) -> Option<&'static T> { let ptr = self.os.get() as *mut Value; if ptr as usize > 1 { - match (*ptr).inner.get() { - Some(ref value) => return Some(value), - None => {}, + if let Some(ref value) = (*ptr).inner.get() { + return Some(value); } } self.try_initialize(init) diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 8be7f4478fa0..51a62cd06584 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1305,7 +1305,8 @@ impl MacroDef { } } -#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy)] +// Clippy uses Hash and PartialEq +#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy, Hash, PartialEq)] pub enum StrStyle { /// A regular string, like `"foo"`. Cooked, @@ -1327,7 +1328,8 @@ pub struct Lit { pub span: Span, } -#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy)] +// Clippy uses Hash and PartialEq +#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy, Hash, PartialEq)] pub enum LitIntType { Signed(IntTy), Unsigned(UintTy), @@ -1337,7 +1339,8 @@ pub enum LitIntType { /// Literal kind. /// /// E.g., `"foo"`, `42`, `12.34`, or `bool`. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +// Clippy uses Hash and PartialEq +#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Hash, PartialEq)] pub enum LitKind { /// A string literal (`"foo"`). Str(Symbol, StrStyle), diff --git a/src/libsyntax/feature_gate/active.rs b/src/libsyntax/feature_gate/active.rs index 94f0995566f5..1386eac48dae 100644 --- a/src/libsyntax/feature_gate/active.rs +++ b/src/libsyntax/feature_gate/active.rs @@ -528,6 +528,9 @@ declare_features! ( /// Enable accurate caller location reporting during panic (RFC 2091). (active, track_caller, "1.40.0", Some(47809), None), + /// Non-object safe trait objects safe to use but cannot be created in safe rust + (active, object_safe_for_dispatch, "1.40.0", Some(43561), None), + // ------------------------------------------------------------------------- // feature-group-end: actual feature gates // ------------------------------------------------------------------------- diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 6bbd8be0cb98..2ce0046ca276 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -86,13 +86,6 @@ macro_rules! maybe_recover_from_interpolated_ty_qpath { } } -fn maybe_append(mut lhs: Vec, mut rhs: Option>) -> Vec { - if let Some(ref mut rhs) = rhs { - lhs.append(rhs); - } - lhs -} - #[derive(Debug, Clone, Copy, PartialEq)] enum PrevTokenKind { DocComment, diff --git a/src/libsyntax/parse/parser/item.rs b/src/libsyntax/parse/parser/item.rs index 0acfd1450d81..73bd80e2a21f 100644 --- a/src/libsyntax/parse/parser/item.rs +++ b/src/libsyntax/parse/parser/item.rs @@ -10,7 +10,6 @@ use crate::ast::{Visibility, VisibilityKind, Mutability, FnHeader, ForeignItem, use crate::ast::{Ty, TyKind, Generics, GenericBounds, TraitRef, EnumDef, VariantData, StructField}; use crate::ast::{Mac, MacDelimiter, Block, BindingMode, FnDecl, MethodSig, SelfKind, Param}; use crate::parse::token; -use crate::parse::parser::maybe_append; use crate::tokenstream::{TokenTree, TokenStream}; use crate::symbol::{kw, sym}; use crate::source_map::{self, respan, Span}; @@ -416,10 +415,17 @@ impl<'a> Parser<'a> { ) -> PResult<'a, Option>> { let (ident, item, extra_attrs) = info; let span = lo.to(self.prev_span); - let attrs = maybe_append(attrs, extra_attrs); + let attrs = Self::maybe_append(attrs, extra_attrs); Ok(Some(self.mk_item(span, ident, item, vis, attrs))) } + fn maybe_append(mut lhs: Vec, mut rhs: Option>) -> Vec { + if let Some(ref mut rhs) = rhs { + lhs.append(rhs); + } + lhs + } + /// This is the fall-through for parsing items. fn parse_macro_use_or_failure( &mut self, diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs index ac155556cdae..0559f224f1f4 100644 --- a/src/libsyntax/tokenstream.rs +++ b/src/libsyntax/tokenstream.rs @@ -19,7 +19,6 @@ use syntax_pos::{BytePos, Span, DUMMY_SP}; #[cfg(target_arch = "x86_64")] use rustc_data_structures::static_assert_size; use rustc_data_structures::sync::Lrc; -use rustc_serialize::{Decoder, Decodable, Encoder, Encodable}; use smallvec::{SmallVec, smallvec}; use std::{iter, mem}; @@ -136,7 +135,7 @@ impl TokenTree { /// The goal is for procedural macros to work with `TokenStream`s and `TokenTree`s /// instead of a representation of the abstract syntax tree. /// Today's `TokenTree`s can still contain AST via `token::Interpolated` for back-compat. -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug, Default, RustcEncodable, RustcDecodable)] pub struct TokenStream(pub Lrc>); pub type TreeAndJoint = (TokenTree, IsJoint); @@ -145,7 +144,7 @@ pub type TreeAndJoint = (TokenTree, IsJoint); #[cfg(target_arch = "x86_64")] static_assert_size!(TokenStream, 8); -#[derive(Clone, Copy, Debug, PartialEq)] +#[derive(Clone, Copy, Debug, PartialEq, RustcEncodable, RustcDecodable)] pub enum IsJoint { Joint, NonJoint @@ -460,18 +459,6 @@ impl Cursor { } } -impl Encodable for TokenStream { - fn encode(&self, encoder: &mut E) -> Result<(), E::Error> { - self.trees().collect::>().encode(encoder) - } -} - -impl Decodable for TokenStream { - fn decode(decoder: &mut D) -> Result { - Vec::::decode(decoder).map(|vec| vec.into_iter().collect()) - } -} - #[derive(Debug, Copy, Clone, PartialEq, RustcEncodable, RustcDecodable)] pub struct DelimSpan { pub open: Span, diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 45d9f79c28fc..37310f46f7ee 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -278,7 +278,7 @@ impl<'a, 'b> Context<'a, 'b> { /// format string. fn report_invalid_references(&self, numbered_position_args: bool) { let mut e; - let sp = if self.is_literal { + let sp = if self.is_literal { // Point at the formatting arguments. MultiSpan::from_spans(self.arg_spans.clone()) } else { MultiSpan::from_span(self.fmtsp) @@ -304,6 +304,9 @@ impl<'a, 'b> Context<'a, 'b> { self.describe_num_args(), ), ); + for arg in &self.args { // Point at the arguments that will be formatted. + e.span_label(arg.span, ""); + } } else { let (mut refs, spans): (Vec<_>, Vec<_>) = refs.unzip(); // Avoid `invalid reference to positional arguments 7 and 7 (there is 1 argument)` diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index fa9567fb62c0..377d2f877b3a 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -9,7 +9,7 @@ use rustc_macros::symbols; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_serialize::{UseSpecializedDecodable, UseSpecializedEncodable}; -use std::cmp::{PartialEq, Ordering, PartialOrd, Ord}; +use std::cmp::{PartialEq, PartialOrd, Ord}; use std::fmt; use std::hash::{Hash, Hasher}; use std::str; @@ -459,6 +459,7 @@ symbols! { no_std, not, note, + object_safe_for_dispatch, Ok, omit_gdb_pretty_printer_section, on, @@ -766,11 +767,6 @@ impl Ident { Ident::with_dummy_span(kw::Invalid) } - /// Maps an interned string to an identifier with an empty syntax context. - pub fn from_interned_str(string: InternedString) -> Ident { - Ident::with_dummy_span(string.as_symbol()) - } - /// Maps a string to an identifier with a dummy span. pub fn from_str(string: &str) -> Ident { Ident::with_dummy_span(Symbol::intern(string)) @@ -813,11 +809,6 @@ impl Ident { pub fn as_str(self) -> LocalInternedString { self.name.as_str() } - - /// Convert the name to an `InternedString`. - pub fn as_interned_str(self) -> InternedString { - self.name.as_interned_str() - } } impl PartialEq for Ident { @@ -903,15 +894,6 @@ impl Symbol { }) } - /// Access two symbols' chars. This is a slowish operation because it - /// requires locking the symbol interner, but it is faster than calling - /// `with()` twice. - fn with2 R, R>(self, other: Symbol, f: F) -> R { - with_interner(|interner| { - f(interner.get(self), interner.get(other)) - }) - } - /// Convert to a `LocalInternedString`. This is a slowish operation because /// it requires locking the symbol interner. pub fn as_str(self) -> LocalInternedString { @@ -922,11 +904,6 @@ impl Symbol { }) } - /// Convert to an `InternedString`. - pub fn as_interned_str(self) -> InternedString { - InternedString { symbol: self } - } - pub fn as_u32(self) -> u32 { self.0.as_u32() } @@ -1105,9 +1082,9 @@ fn with_interner T>(f: F) -> T { GLOBALS.with(|globals| f(&mut *globals.symbol_interner.lock())) } -/// An alternative to `Symbol` and `InternedString`, useful when the chars -/// within the symbol need to be accessed. It deliberately has limited -/// functionality and should only be used for temporary values. +/// An alternative to `Symbol`, useful when the chars within the symbol need to +/// be accessed. It deliberately has limited functionality and should only be +/// used for temporary values. /// /// Because the interner outlives any thread which uses this type, we can /// safely treat `string` which points to interner data, as an immortal string, @@ -1116,7 +1093,7 @@ fn with_interner T>(f: F) -> T { // FIXME: ensure that the interner outlives any thread which uses // `LocalInternedString`, by creating a new thread right after constructing the // interner. -#[derive(Eq, PartialOrd, Ord)] +#[derive(Clone, Eq, PartialOrd, Ord)] pub struct LocalInternedString { string: &'static str, } @@ -1157,89 +1134,3 @@ impl fmt::Display for LocalInternedString { fmt::Display::fmt(self.string, f) } } - -/// An alternative to `Symbol` that is focused on string contents. -/// -/// Its implementations of `Hash`, `PartialOrd` and `Ord` work with the -/// string chars rather than the symbol integer. This is useful when hash -/// stability is required across compile sessions, or a guaranteed sort -/// ordering is required. -#[derive(Clone, Copy, PartialEq, Eq)] -pub struct InternedString { - symbol: Symbol, -} - -impl InternedString { - /// Maps a string to its interned representation. - pub fn intern(string: &str) -> Self { - InternedString { - symbol: Symbol::intern(string) - } - } - - pub fn with R, R>(self, f: F) -> R { - self.symbol.with(f) - } - - fn with2 R, R>(self, other: &InternedString, f: F) -> R { - self.symbol.with2(other.symbol, f) - } - - pub fn as_symbol(self) -> Symbol { - self.symbol - } - - /// Convert to a `LocalInternedString`. This is a slowish operation because it - /// requires locking the symbol interner. - pub fn as_str(self) -> LocalInternedString { - self.symbol.as_str() - } -} - -impl Hash for InternedString { - fn hash(&self, state: &mut H) { - self.with(|str| str.hash(state)) - } -} - -impl PartialOrd for InternedString { - fn partial_cmp(&self, other: &InternedString) -> Option { - if self.symbol == other.symbol { - return Some(Ordering::Equal); - } - self.with2(other, |self_str, other_str| self_str.partial_cmp(other_str)) - } -} - -impl Ord for InternedString { - fn cmp(&self, other: &InternedString) -> Ordering { - if self.symbol == other.symbol { - return Ordering::Equal; - } - self.with2(other, |self_str, other_str| self_str.cmp(other_str)) - } -} - -impl fmt::Debug for InternedString { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.with(|str| fmt::Debug::fmt(&str, f)) - } -} - -impl fmt::Display for InternedString { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.with(|str| fmt::Display::fmt(&str, f)) - } -} - -impl Decodable for InternedString { - fn decode(d: &mut D) -> Result { - Ok(InternedString::intern(&d.read_str()?)) - } -} - -impl Encodable for InternedString { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { - self.with(|string| s.emit_str(string)) - } -} diff --git a/src/libtest/bench.rs b/src/libtest/bench.rs index c142c5213d2e..c86bfd16c21b 100644 --- a/src/libtest/bench.rs +++ b/src/libtest/bench.rs @@ -48,7 +48,7 @@ impl Bencher { F: FnMut(&mut Bencher), { f(self); - return self.summary; + self.summary } } @@ -116,7 +116,7 @@ where for _ in 0..k { black_box(inner()); } - return ns_from_dur(start.elapsed()); + ns_from_dur(start.elapsed()) } pub fn iter(inner: &mut F) -> stats::Summary diff --git a/src/libtest/cli.rs b/src/libtest/cli.rs index f95d5aad18a6..a34426305be2 100644 --- a/src/libtest/cli.rs +++ b/src/libtest/cli.rs @@ -149,7 +149,7 @@ fn optgroups() -> getopts::Options { `CRITICAL_TIME` here means the limit that should not be exceeded by test. " ); - return opts; + opts } fn usage(binary: &str, options: &getopts::Options) { diff --git a/src/libtest/console.rs b/src/libtest/console.rs index e17030726cea..244cbd2cf5fe 100644 --- a/src/libtest/console.rs +++ b/src/libtest/console.rs @@ -296,7 +296,7 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec) -> io::Resu assert!(st.current_test_count() == st.total); - return out.write_run_finish(&st); + out.write_run_finish(&st) } // Calculates padding for given test description. diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 179558e8f9a1..8c1e9f1722a2 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -34,8 +34,10 @@ pub use self::ColorConfig::*; pub use self::types::*; pub use self::types::TestName::*; -pub use self::options::{Options, ShouldPanic}; +pub use self::options::{ColorConfig, Options, OutputFormat, RunIgnored, ShouldPanic}; pub use self::bench::{Bencher, black_box}; +pub use self::console::run_tests_console; +pub use cli::TestOpts; // Module to be used by rustc to compile tests in libtest pub mod test { @@ -84,9 +86,8 @@ mod tests; use test_result::*; use time::TestExecTime; -use options::{RunStrategy, Concurrent, RunIgnored, ColorConfig}; +use options::{RunStrategy, Concurrent}; use event::{CompletedTest, TestEvent}; -use cli::TestOpts; use helpers::sink::Sink; use helpers::concurrency::get_concurrency; use helpers::exit_code::get_exit_code; diff --git a/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs b/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs index 1566a153ec03..eb96c61060b3 100644 --- a/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs +++ b/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs @@ -9,14 +9,14 @@ extern crate rustc_target; extern crate rustc_driver; use std::any::Any; -use std::sync::{Arc, mpsc}; +use std::sync::Arc; use std::path::Path; use syntax::symbol::Symbol; use rustc::session::Session; use rustc::session::config::OutputFilenames; use rustc::ty::TyCtxt; use rustc::ty::query::Providers; -use rustc::middle::cstore::{EncodedMetadata, MetadataLoader}; +use rustc::middle::cstore::{EncodedMetadata, MetadataLoader, MetadataLoaderDyn}; use rustc::dep_graph::DepGraph; use rustc::util::common::ErrorReported; use rustc_codegen_utils::codegen_backend::CodegenBackend; @@ -41,7 +41,7 @@ impl MetadataLoader for NoLlvmMetadataLoader { struct TheBackend; impl CodegenBackend for TheBackend { - fn metadata_loader(&self) -> Box { + fn metadata_loader(&self) -> Box { Box::new(NoLlvmMetadataLoader) } diff --git a/src/test/run-make-fulldeps/issue-19371/foo.rs b/src/test/run-make-fulldeps/issue-19371/foo.rs index e290f7fa6b13..9582137eae91 100644 --- a/src/test/run-make-fulldeps/issue-19371/foo.rs +++ b/src/test/run-make-fulldeps/issue-19371/foo.rs @@ -59,6 +59,7 @@ fn compile(code: String, output: PathBuf, sysroot: PathBuf) { stderr: None, crate_name: None, lint_caps: Default::default(), + register_lints: None, }; interface::run_compiler(config, |compiler| { diff --git a/src/test/rustdoc/const-generics/const-impl.rs b/src/test/rustdoc/const-generics/const-impl.rs index 85ee6d3376b2..2d506787b3b8 100644 --- a/src/test/rustdoc/const-generics/const-impl.rs +++ b/src/test/rustdoc/const-generics/const-impl.rs @@ -4,6 +4,7 @@ #![crate_name = "foo"] +#[derive(PartialEq, Eq)] pub enum Order { Sorted, Unsorted, diff --git a/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs b/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs index bb0ebf693d0b..6b914f501ca7 100644 --- a/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs +++ b/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs @@ -15,15 +15,14 @@ use syntax::symbol::Symbol; use rustc::hir; use rustc::hir::intravisit; -use rustc::hir::map as hir_map; use hir::Node; use rustc::lint::{LateContext, LintPass, LintArray, LateLintPass, LintContext}; -use rustc::ty; -use syntax::{ast, source_map}; +use syntax::source_map; #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { - reg.register_late_lint_pass(box MissingWhitelistedAttrPass); + reg.lint_store.register_lints(&[&MISSING_WHITELISTED_ATTR]); + reg.lint_store.register_late_pass(|| box MissingWhitelistedAttrPass); reg.register_attribute(Symbol::intern("whitelisted_attr"), Whitelisted); } diff --git a/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs b/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs index 17386d7e1aa5..6874c921c1cc 100644 --- a/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs +++ b/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs @@ -7,24 +7,20 @@ extern crate rustc_driver; extern crate syntax; -use rustc::lint::{LateContext, LintContext, LintPass, LateLintPass, LateLintPassObject, LintArray}; +use rustc::lint::{LateContext, LintContext, LintPass, LateLintPass}; use rustc_driver::plugin::Registry; use rustc::hir; use syntax::attr; use syntax::symbol::Symbol; macro_rules! fake_lint_pass { - ($struct:ident, $lints:expr, $($attr:expr),*) => { + ($struct:ident, $($attr:expr),*) => { struct $struct; impl LintPass for $struct { fn name(&self) -> &'static str { stringify!($struct) } - - fn get_lints(&self) -> LintArray { - $lints - } } impl<'a, 'tcx> LateLintPass<'a, 'tcx> for $struct { @@ -49,25 +45,29 @@ declare_lint!(CRATE_NOT_GREEN, Warn, "crate not marked with #![crate_green]"); fake_lint_pass! { PassOkay, - lint_array!(CRATE_NOT_OKAY), // Single lint Symbol::intern("rustc_crate_okay") } fake_lint_pass! { PassRedBlue, - lint_array!(CRATE_NOT_RED, CRATE_NOT_BLUE), // Multiple lints Symbol::intern("rustc_crate_red"), Symbol::intern("rustc_crate_blue") } fake_lint_pass! { PassGreyGreen, - lint_array!(CRATE_NOT_GREY, CRATE_NOT_GREEN, ), // Trailing comma Symbol::intern("rustc_crate_grey"), Symbol::intern("rustc_crate_green") } #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { - reg.register_late_lint_pass(box PassOkay); - reg.register_late_lint_pass(box PassRedBlue); - reg.register_late_lint_pass(box PassGreyGreen); + reg.lint_store.register_lints(&[ + &CRATE_NOT_OKAY, + &CRATE_NOT_RED, + &CRATE_NOT_BLUE, + &CRATE_NOT_GREY, + &CRATE_NOT_GREEN, + ]); + reg.lint_store.register_late_pass(|| box PassOkay); + reg.lint_store.register_late_pass(|| box PassRedBlue); + reg.lint_store.register_late_pass(|| box PassGreyGreen); } diff --git a/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs b/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs index 000e10392e82..1cd3e7b28dba 100644 --- a/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs +++ b/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs @@ -7,7 +7,7 @@ extern crate rustc_driver; extern crate syntax; -use rustc::lint::{LateContext, LintContext, LintPass, LateLintPass, LateLintPassObject, LintArray}; +use rustc::lint::{LateContext, LintContext, LintPass, LateLintPass, LintArray}; use rustc_driver::plugin::Registry; use rustc::hir; use syntax::attr; @@ -32,5 +32,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { - reg.register_late_lint_pass(box Pass); + reg.lint_store.register_lints(&[&CRATE_NOT_OKAY]); + reg.lint_store.register_late_pass(|| box Pass); } diff --git a/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs b/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs index a377b07bd3dd..cb793b434988 100644 --- a/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs +++ b/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs @@ -9,7 +9,7 @@ extern crate rustc; extern crate rustc_driver; use rustc::hir; -use rustc::lint::{LateContext, LintContext, LintPass, LateLintPass, LateLintPassObject, LintArray}; +use rustc::lint::{LateContext, LintContext, LintPass, LateLintPass, LintArray, LintId}; use rustc_driver::plugin::Registry; declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'"); @@ -30,6 +30,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { - reg.register_late_lint_pass(box Pass); - reg.register_lint_group("lint_me", None, vec![TEST_LINT, PLEASE_LINT]); + reg.lint_store.register_lints(&[&TEST_LINT, &PLEASE_LINT]); + reg.lint_store.register_late_pass(|| box Pass); + reg.lint_store.register_group(true, "lint_me", None, + vec![LintId::of(&TEST_LINT), LintId::of(&PLEASE_LINT)]); } diff --git a/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs b/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs index 02675191f785..40c37eb570e2 100644 --- a/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs +++ b/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs @@ -10,8 +10,7 @@ extern crate syntax; extern crate rustc; extern crate rustc_driver; -use rustc::lint::{EarlyContext, LintContext, LintPass, EarlyLintPass, - EarlyLintPassObject, LintArray}; +use rustc::lint::{EarlyContext, LintContext, LintPass, EarlyLintPass, LintArray}; use rustc_driver::plugin::Registry; use syntax::ast; declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'"); @@ -28,5 +27,6 @@ impl EarlyLintPass for Pass { #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { - reg.register_early_lint_pass(box Pass as EarlyLintPassObject); + reg.lint_store.register_lints(&[&TEST_LINT]); + reg.lint_store.register_early_pass(|| box Pass); } diff --git a/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs b/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs index 40f8d490ac87..67135d595f44 100644 --- a/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs +++ b/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs @@ -8,7 +8,7 @@ extern crate syntax; extern crate rustc; extern crate rustc_driver; -use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass}; +use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass, LintId}; use rustc_driver::plugin::Registry; use syntax::ast; declare_tool_lint!(pub clippy::TEST_LINT, Warn, "Warn about stuff"); @@ -40,6 +40,8 @@ impl EarlyLintPass for Pass { #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { - reg.register_early_lint_pass(box Pass); - reg.register_lint_group("clippy::group", Some("clippy_group"), vec![TEST_LINT, TEST_GROUP]); + reg.lint_store.register_lints(&[&TEST_RUSTC_TOOL_LINT, &TEST_LINT, &TEST_GROUP]); + reg.lint_store.register_early_pass(|| box Pass); + reg.lint_store.register_group(true, "clippy::group", Some("clippy_group"), + vec![LintId::of(&TEST_LINT), LintId::of(&TEST_GROUP)]); } diff --git a/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.rs b/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.rs index 48dd5b122b5a..0bfb32c6dc43 100644 --- a/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.rs +++ b/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.rs @@ -6,7 +6,7 @@ extern crate rustc; use rustc::lint::{LintArray, LintPass}; -use rustc::{declare_lint, declare_lint_pass, impl_lint_pass, lint_array}; +use rustc::{declare_lint, declare_lint_pass, impl_lint_pass}; declare_lint! { pub TEST_LINT, @@ -17,10 +17,6 @@ declare_lint! { struct Foo; impl LintPass for Foo { //~ERROR implementing `LintPass` by hand - fn get_lints(&self) -> LintArray { - lint_array!(TEST_LINT) - } - fn name(&self) -> &'static str { "Foo" } @@ -31,10 +27,6 @@ macro_rules! custom_lint_pass_macro { struct Custom; impl LintPass for Custom { //~ERROR implementing `LintPass` by hand - fn get_lints(&self) -> LintArray { - lint_array!(TEST_LINT) - } - fn name(&self) -> &'static str { "Custom" } diff --git a/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr b/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr index b439ae2cd148..0dbdf4f5aa9e 100644 --- a/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr +++ b/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr @@ -12,7 +12,7 @@ LL | #![deny(rustc::lint_pass_impl_without_macro)] = help: try using `declare_lint_pass!` or `impl_lint_pass!` instead error: implementing `LintPass` by hand - --> $DIR/lint_pass_impl_without_macro.rs:33:14 + --> $DIR/lint_pass_impl_without_macro.rs:29:14 | LL | impl LintPass for Custom { | ^^^^^^^^ diff --git a/src/test/ui/asm/issue-51431.rs b/src/test/ui/asm/issue-51431.rs new file mode 100644 index 000000000000..d29c31fafc28 --- /dev/null +++ b/src/test/ui/asm/issue-51431.rs @@ -0,0 +1,10 @@ +// ignore-emscripten no asm! support + +#![feature(asm)] + +fn main() { + unsafe { + asm! {"mov $0,$1"::"0"("bx"),"1"(0x00)} + //~^ ERROR: invalid value for constraint in inline assembly + } +} diff --git a/src/test/ui/asm/issue-51431.stderr b/src/test/ui/asm/issue-51431.stderr new file mode 100644 index 000000000000..132eea126d64 --- /dev/null +++ b/src/test/ui/asm/issue-51431.stderr @@ -0,0 +1,8 @@ +error[E0669]: invalid value for constraint in inline assembly + --> $DIR/issue-51431.rs:7:32 + | +LL | asm! {"mov $0,$1"::"0"("bx"),"1"(0x00)} + | ^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/associated-const/issue-63496.rs b/src/test/ui/associated-const/issue-63496.rs new file mode 100644 index 000000000000..311c48b5e48c --- /dev/null +++ b/src/test/ui/associated-const/issue-63496.rs @@ -0,0 +1,9 @@ +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 +} + +fn main() {} diff --git a/src/test/ui/associated-const/issue-63496.stderr b/src/test/ui/associated-const/issue-63496.stderr new file mode 100644 index 000000000000..70bb12de1fb7 --- /dev/null +++ b/src/test/ui/associated-const/issue-63496.stderr @@ -0,0 +1,21 @@ +error[E0283]: type annotations needed: cannot resolve `_: A` + --> $DIR/issue-63496.rs:4:21 + | +LL | const C: usize; + | --------------- required by `A::C` +LL | +LL | fn f() -> ([u8; A::C], [u8; A::C]); + | ^^^^ + +error[E0283]: type annotations needed: cannot resolve `_: A` + --> $DIR/issue-63496.rs:4:33 + | +LL | const C: usize; + | --------------- required by `A::C` +LL | +LL | fn f() -> ([u8; A::C], [u8; A::C]); + | ^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0283`. diff --git a/src/test/ui/ast-json/ast-json-output.stdout b/src/test/ui/ast-json/ast-json-output.stdout index 563885133a4c..64c9f6931158 100644 --- a/src/test/ui/ast-json/ast-json-output.stdout +++ b/src/test/ui/ast-json/ast-json-output.stdout @@ -1 +1 @@ -{"module":{"inner":{"lo":0,"hi":0},"items":[{"ident":{"name":"core","span":{"lo":0,"hi":0}},"attrs":[],"id":0,"kind":{"variant":"ExternCrate","fields":[null]},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"span":{"lo":0,"hi":0},"tokens":[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["extern",false]},"span":{"lo":0,"hi":0}}]},{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate",false]},"span":{"lo":0,"hi":0}}]},{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["core",false]},"span":{"lo":0,"hi":0}}]},{"variant":"Token","fields":[{"kind":"Semi","span":{"lo":0,"hi":0}}]}]}],"inline":true},"attrs":[],"span":{"lo":0,"hi":0}} +{"module":{"inner":{"lo":0,"hi":0},"items":[{"ident":{"name":"core","span":{"lo":0,"hi":0}},"attrs":[],"id":0,"kind":{"variant":"ExternCrate","fields":[null]},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"span":{"lo":0,"hi":0},"tokens":{"_field0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["extern",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["core",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":"Semi","span":{"lo":0,"hi":0}}]},"NonJoint"]]}}],"inline":true},"attrs":[],"span":{"lo":0,"hi":0}} diff --git a/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr b/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr index 7caa9f26bc2f..4b5e2d59e38c 100644 --- a/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr +++ b/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr @@ -244,4 +244,5 @@ LL | let _ = await bar()?; error: aborting due to 35 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0277, E0728. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/async-await/issues/issue-51719.stderr b/src/test/ui/async-await/issues/issue-51719.stderr index 6c3c8889da7c..5b9adb253d96 100644 --- a/src/test/ui/async-await/issues/issue-51719.stderr +++ b/src/test/ui/async-await/issues/issue-51719.stderr @@ -8,3 +8,4 @@ LL | let _gen = || foo().await; error: aborting due to previous error +For more information about this error, try `rustc --explain E0728`. diff --git a/src/test/ui/async-await/issues/issue-51751.stderr b/src/test/ui/async-await/issues/issue-51751.stderr index e50c78534f85..f120bd119c54 100644 --- a/src/test/ui/async-await/issues/issue-51751.stderr +++ b/src/test/ui/async-await/issues/issue-51751.stderr @@ -9,3 +9,4 @@ LL | let finished = result.await; error: aborting due to previous error +For more information about this error, try `rustc --explain E0728`. diff --git a/src/test/ui/async-await/issues/issue-62009-1.stderr b/src/test/ui/async-await/issues/issue-62009-1.stderr index f63eaa4c48a9..538430290d29 100644 --- a/src/test/ui/async-await/issues/issue-62009-1.stderr +++ b/src/test/ui/async-await/issues/issue-62009-1.stderr @@ -40,4 +40,5 @@ LL | F: Future error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0277, E0728. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/async-await/issues/issue-62009-2.stderr b/src/test/ui/async-await/issues/issue-62009-2.stderr index 79b6803263ee..47b74b5574fe 100644 --- a/src/test/ui/async-await/issues/issue-62009-2.stderr +++ b/src/test/ui/async-await/issues/issue-62009-2.stderr @@ -8,3 +8,4 @@ LL | (async || 2333)().await; error: aborting due to previous error +For more information about this error, try `rustc --explain E0728`. diff --git a/src/test/ui/async-await/issues/non-async-enclosing-span.stderr b/src/test/ui/async-await/issues/non-async-enclosing-span.stderr index 49ebf414c550..f826a86f0898 100644 --- a/src/test/ui/async-await/issues/non-async-enclosing-span.stderr +++ b/src/test/ui/async-await/issues/non-async-enclosing-span.stderr @@ -9,3 +9,4 @@ LL | let y = do_the_thing().await; error: aborting due to previous error +For more information about this error, try `rustc --explain E0728`. diff --git a/src/test/ui/break-outside-loop.rs b/src/test/ui/break-outside-loop.rs index c424c25c646b..a6f9d0423d08 100644 --- a/src/test/ui/break-outside-loop.rs +++ b/src/test/ui/break-outside-loop.rs @@ -22,4 +22,12 @@ fn main() { let rs: Foo = Foo{t: pth}; let unconstrained = break; //~ ERROR: `break` outside of a loop + + // This used to ICE because `target_id` passed to `check_expr_break` would be the closure and + // not the `loop`, which failed in the call to `find_breakable`. (#65383) + 'lab: loop { + || { + break 'lab; //~ ERROR `break` inside of a closure + }; + } } diff --git a/src/test/ui/break-outside-loop.stderr b/src/test/ui/break-outside-loop.stderr index 8b686356055a..8e300fd848da 100644 --- a/src/test/ui/break-outside-loop.stderr +++ b/src/test/ui/break-outside-loop.stderr @@ -33,7 +33,15 @@ error[E0268]: `break` outside of a loop LL | let unconstrained = break; | ^^^^^ cannot `break` outside of a loop -error: aborting due to 5 previous errors +error[E0267]: `break` inside of a closure + --> $DIR/break-outside-loop.rs:30:13 + | +LL | || { + | -- enclosing closure +LL | break 'lab; + | ^^^^^^^^^^ cannot `break` inside of a closure + +error: aborting due to 6 previous errors Some errors have detailed explanations: E0267, E0268. For more information about an error, try `rustc --explain E0267`. diff --git a/src/test/ui/closures/issue-41366.rs b/src/test/ui/closures/issue-41366.rs new file mode 100644 index 000000000000..5cae0e76d1ac --- /dev/null +++ b/src/test/ui/closures/issue-41366.rs @@ -0,0 +1,13 @@ +trait T<'x> { + type V; +} + +impl<'g> T<'g> for u32 { + type V = u16; +} + +fn main() { + (&|_|()) as &dyn for<'x> Fn(>::V); + //~^ ERROR: type mismatch in closure arguments + //~| ERROR: type mismatch resolving +} diff --git a/src/test/ui/closures/issue-41366.stderr b/src/test/ui/closures/issue-41366.stderr new file mode 100644 index 000000000000..91d26efbc4f3 --- /dev/null +++ b/src/test/ui/closures/issue-41366.stderr @@ -0,0 +1,22 @@ +error[E0631]: type mismatch in closure arguments + --> $DIR/issue-41366.rs:10:5 + | +LL | (&|_|()) as &dyn for<'x> Fn(>::V); + | ^^-----^ + | | | + | | found signature of `fn(_) -> _` + | expected signature of `for<'x> fn(>::V) -> _` + | + = note: required for the cast to the object type `dyn for<'x> std::ops::Fn(>::V)` + +error[E0271]: type mismatch resolving `for<'x> <[closure@$DIR/issue-41366.rs:10:7: 10:12] as std::ops::FnOnce<(>::V,)>>::Output == ()` + --> $DIR/issue-41366.rs:10:5 + | +LL | (&|_|()) as &dyn for<'x> Fn(>::V); + | ^^^^^^^^ expected bound lifetime parameter 'x, found concrete lifetime + | + = note: required for the cast to the object type `dyn for<'x> std::ops::Fn(>::V)` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/closures/issue-52437.rs b/src/test/ui/closures/issue-52437.rs new file mode 100644 index 000000000000..6ac5380a5aa2 --- /dev/null +++ b/src/test/ui/closures/issue-52437.rs @@ -0,0 +1,5 @@ +fn main() { + [(); &(&'static: loop { |x| {}; }) as *const _ as usize] + //~^ ERROR: invalid label name `'static` + //~| ERROR: type annotations needed +} diff --git a/src/test/ui/closures/issue-52437.stderr b/src/test/ui/closures/issue-52437.stderr new file mode 100644 index 000000000000..e76f942e9ba5 --- /dev/null +++ b/src/test/ui/closures/issue-52437.stderr @@ -0,0 +1,15 @@ +error: invalid label name `'static` + --> $DIR/issue-52437.rs:2:13 + | +LL | [(); &(&'static: loop { |x| {}; }) as *const _ as usize] + | ^^^^^^^ + +error[E0282]: type annotations needed + --> $DIR/issue-52437.rs:2:30 + | +LL | [(); &(&'static: loop { |x| {}; }) as *const _ as usize] + | ^ consider giving this closure parameter a type + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/coherence/coherence-unsafe-trait-object-impl.rs b/src/test/ui/coherence/coherence-unsafe-trait-object-impl.rs new file mode 100644 index 000000000000..9859a226efd0 --- /dev/null +++ b/src/test/ui/coherence/coherence-unsafe-trait-object-impl.rs @@ -0,0 +1,18 @@ +// Check that unsafe trait object do not implement themselves +// automatically + +#![feature(object_safe_for_dispatch)] + +trait Trait: Sized { + fn call(&self); +} + +fn takes_t(s: S) { + s.call(); +} + +fn takes_t_obj(t: &dyn Trait) { + takes_t(t); //~ ERROR E0277 +} + +fn main() {} diff --git a/src/test/ui/coherence/coherence-unsafe-trait-object-impl.stderr b/src/test/ui/coherence/coherence-unsafe-trait-object-impl.stderr new file mode 100644 index 000000000000..b5a86acfb978 --- /dev/null +++ b/src/test/ui/coherence/coherence-unsafe-trait-object-impl.stderr @@ -0,0 +1,12 @@ +error[E0277]: the trait bound `&dyn Trait: Trait` is not satisfied + --> $DIR/coherence-unsafe-trait-object-impl.rs:15:13 + | +LL | fn takes_t(s: S) { + | ------- ----- required by this bound in `takes_t` +... +LL | takes_t(t); + | ^ the trait `Trait` is not implemented for `&dyn Trait` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/coherence/impl-foreign-for-foreign.rs b/src/test/ui/coherence/impl-foreign-for-foreign.rs new file mode 100644 index 000000000000..de0b66a35eb0 --- /dev/null +++ b/src/test/ui/coherence/impl-foreign-for-foreign.rs @@ -0,0 +1,17 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote for i32 { + //~^ ERROR only traits defined in the current crate + // | can be implemented for arbitrary types [E0117] +} + +fn main() {} diff --git a/src/test/ui/coherence/impl-foreign-for-foreign.stderr b/src/test/ui/coherence/impl-foreign-for-foreign.stderr new file mode 100644 index 000000000000..b03a75a77c34 --- /dev/null +++ b/src/test/ui/coherence/impl-foreign-for-foreign.stderr @@ -0,0 +1,12 @@ +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/impl-foreign-for-foreign.rs:12:1 + | +LL | impl Remote for i32 { + | ^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate + | + = note: the impl does not reference only types defined in this crate + = note: define and implement a trait or new type instead + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0117`. diff --git a/src/test/ui/coherence/impl-foreign-for-foreign[foreign].rs b/src/test/ui/coherence/impl-foreign-for-foreign[foreign].rs new file mode 100644 index 000000000000..5146263d9911 --- /dev/null +++ b/src/test/ui/coherence/impl-foreign-for-foreign[foreign].rs @@ -0,0 +1,25 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote1> for i32 { + //~^ ERROR only traits defined in the current crate + // | can be implemented for arbitrary types [E0117] +} +impl Remote1> for f64 { + //~^ ERROR only traits defined in the current crate + // | can be implemented for arbitrary types [E0117] +} +impl Remote1> for f32 { + //~^ ERROR only traits defined in the current crate + // | can be implemented for arbitrary types [E0117] +} + +fn main() {} diff --git a/src/test/ui/coherence/impl-foreign-for-foreign[foreign].stderr b/src/test/ui/coherence/impl-foreign-for-foreign[foreign].stderr new file mode 100644 index 000000000000..bfaec790b20a --- /dev/null +++ b/src/test/ui/coherence/impl-foreign-for-foreign[foreign].stderr @@ -0,0 +1,30 @@ +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/impl-foreign-for-foreign[foreign].rs:12:1 + | +LL | impl Remote1> for i32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate + | + = note: the impl does not reference only types defined in this crate + = note: define and implement a trait or new type instead + +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/impl-foreign-for-foreign[foreign].rs:16:1 + | +LL | impl Remote1> for f64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate + | + = note: the impl does not reference only types defined in this crate + = note: define and implement a trait or new type instead + +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/impl-foreign-for-foreign[foreign].rs:20:1 + | +LL | impl Remote1> for f32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate + | + = note: the impl does not reference only types defined in this crate + = note: define and implement a trait or new type instead + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0117`. diff --git a/src/test/ui/coherence/impl-foreign-for-foreign[local].rs b/src/test/ui/coherence/impl-foreign-for-foreign[local].rs new file mode 100644 index 000000000000..050769dcf4ce --- /dev/null +++ b/src/test/ui/coherence/impl-foreign-for-foreign[local].rs @@ -0,0 +1,16 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs +// check-pass + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local(Rc); + +impl Remote1> for i32 {} +impl Remote1> for f32 {} + +fn main() {} diff --git a/src/test/ui/coherence/impl-foreign-for-fundamental[foreign].rs b/src/test/ui/coherence/impl-foreign-for-fundamental[foreign].rs new file mode 100644 index 000000000000..03b11edf98b4 --- /dev/null +++ b/src/test/ui/coherence/impl-foreign-for-fundamental[foreign].rs @@ -0,0 +1,21 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote for Box { + //~^ ERROR only traits defined in the current crate + // | can be implemented for arbitrary types [E0117] +} +impl Remote for Box> { + //~^ ERROR only traits defined in the current crate + // | can be implemented for arbitrary types [E0117] +} + +fn main() {} diff --git a/src/test/ui/coherence/impl-foreign-for-fundamental[foreign].stderr b/src/test/ui/coherence/impl-foreign-for-fundamental[foreign].stderr new file mode 100644 index 000000000000..2ce4921cf938 --- /dev/null +++ b/src/test/ui/coherence/impl-foreign-for-fundamental[foreign].stderr @@ -0,0 +1,21 @@ +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/impl-foreign-for-fundamental[foreign].rs:12:1 + | +LL | impl Remote for Box { + | ^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate + | + = note: the impl does not reference only types defined in this crate + = note: define and implement a trait or new type instead + +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/impl-foreign-for-fundamental[foreign].rs:16:1 + | +LL | impl Remote for Box> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate + | + = note: the impl does not reference only types defined in this crate + = note: define and implement a trait or new type instead + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0117`. diff --git a/src/test/ui/coherence/impl-foreign-for-fundamental[local].rs b/src/test/ui/coherence/impl-foreign-for-fundamental[local].rs new file mode 100644 index 000000000000..ae03ce6a440d --- /dev/null +++ b/src/test/ui/coherence/impl-foreign-for-fundamental[local].rs @@ -0,0 +1,17 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs +// check-pass + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; +struct Local1(Rc); + +impl Remote for Box {} +impl Remote for Box> {} + +fn main() {} diff --git a/src/test/ui/coherence/impl-foreign-for-local.rs b/src/test/ui/coherence/impl-foreign-for-local.rs new file mode 100644 index 000000000000..c9dddeba18dc --- /dev/null +++ b/src/test/ui/coherence/impl-foreign-for-local.rs @@ -0,0 +1,15 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs +// check-pass + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote for Local {} + +fn main() {} diff --git a/src/test/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.rs b/src/test/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.rs new file mode 100644 index 000000000000..06efb6c2ad75 --- /dev/null +++ b/src/test/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.rs @@ -0,0 +1,26 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; +struct Local1(Rc); + +impl Remote1> for i32 { + //~^ ERROR only traits defined in the current crate + // | can be implemented for arbitrary types [E0117] +} +impl Remote1>> for f64 { + //~^ ERROR only traits defined in the current crate + // | can be implemented for arbitrary types [E0117] +} +impl Remote1>> for f32 { + //~^ ERROR only traits defined in the current crate + // | can be implemented for arbitrary types [E0117] +} + +fn main() {} diff --git a/src/test/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.stderr b/src/test/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.stderr new file mode 100644 index 000000000000..bf2361a1718a --- /dev/null +++ b/src/test/ui/coherence/impl-foreign[fundemental[foreign]]-for-foreign.stderr @@ -0,0 +1,30 @@ +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/impl-foreign[fundemental[foreign]]-for-foreign.rs:13:1 + | +LL | impl Remote1> for i32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate + | + = note: the impl does not reference only types defined in this crate + = note: define and implement a trait or new type instead + +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/impl-foreign[fundemental[foreign]]-for-foreign.rs:17:1 + | +LL | impl Remote1>> for f64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate + | + = note: the impl does not reference only types defined in this crate + = note: define and implement a trait or new type instead + +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/impl-foreign[fundemental[foreign]]-for-foreign.rs:21:1 + | +LL | impl Remote1>> for f32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate + | + = note: the impl does not reference only types defined in this crate + = note: define and implement a trait or new type instead + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0117`. diff --git a/src/test/ui/coherence/impl-foreign[fundemental[local]]-for-foreign.rs b/src/test/ui/coherence/impl-foreign[fundemental[local]]-for-foreign.rs new file mode 100644 index 000000000000..d47e0a36a565 --- /dev/null +++ b/src/test/ui/coherence/impl-foreign[fundemental[local]]-for-foreign.rs @@ -0,0 +1,18 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs +// check-pass + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; +struct Local1(Rc); + +impl Remote1> for i32 {} +impl Remote1>> for f64 {} +impl Remote1>> for f32 {} + +fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign-for-foreign[t].rs b/src/test/ui/coherence/impl[t]-foreign-for-foreign[t].rs new file mode 100644 index 000000000000..db7a2ae8076a --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign-for-foreign[t].rs @@ -0,0 +1,23 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; +use std::sync::Arc; + +struct Local; + +impl Remote for Rc { + //~^ ERROR only traits defined in the current crate + // | can be implemented for arbitrary types [E0117] +} + +impl Remote for Arc { + //~^ ERROR only traits defined in the current crate + // | can be implemented for arbitrary types [E0117] +} + +fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign-for-foreign[t].stderr b/src/test/ui/coherence/impl[t]-foreign-for-foreign[t].stderr new file mode 100644 index 000000000000..d7ffcaf76f9a --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign-for-foreign[t].stderr @@ -0,0 +1,21 @@ +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/impl[t]-foreign-for-foreign[t].rs:13:1 + | +LL | impl Remote for Rc { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate + | + = note: the impl does not reference only types defined in this crate + = note: define and implement a trait or new type instead + +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/impl[t]-foreign-for-foreign[t].rs:18:1 + | +LL | impl Remote for Arc { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate + | + = note: the impl does not reference only types defined in this crate + = note: define and implement a trait or new type instead + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0117`. diff --git a/src/test/ui/coherence/impl[t]-foreign-for-fundamental[t].rs b/src/test/ui/coherence/impl[t]-foreign-for-fundamental[t].rs new file mode 100644 index 000000000000..4cc19e1a526c --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign-for-fundamental[t].rs @@ -0,0 +1,17 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote for Box { + //~^ ERROR type parameter `T` must be used as the type parameter for + // | some local type (e.g., `MyStruct`) +} + +fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign-for-fundamental[t].stderr b/src/test/ui/coherence/impl[t]-foreign-for-fundamental[t].stderr new file mode 100644 index 000000000000..20ce11ef9759 --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign-for-fundamental[t].stderr @@ -0,0 +1,11 @@ +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign-for-fundamental[t].rs:12:1 + | +LL | impl Remote for Box { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type + | + = note: only traits defined in the current crate can be implemented for a type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0210`. diff --git a/src/test/ui/coherence/impl[t]-foreign[fundemental[local]]-for-foreign[t].rs b/src/test/ui/coherence/impl[t]-foreign[fundemental[local]]-for-foreign[t].rs new file mode 100644 index 000000000000..914680f191ac --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[fundemental[local]]-for-foreign[t].rs @@ -0,0 +1,17 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs +// check-pass + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; +struct Local1(Rc); + +impl Remote1> for Rc {} +impl Remote1>> for Rc {} + +fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[local]-for-foreign[t].rs b/src/test/ui/coherence/impl[t]-foreign[local]-for-foreign[t].rs new file mode 100644 index 000000000000..1e84ff40c622 --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[local]-for-foreign[t].rs @@ -0,0 +1,17 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs +// check-pass + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; +struct Local1(Rc); + +impl Remote1 for Rc {} +impl Remote1> for Rc {} + +fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[foreign[t]].rs b/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[foreign[t]].rs new file mode 100644 index 000000000000..ea6aa101d209 --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[foreign[t]].rs @@ -0,0 +1,19 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs +// check-pass + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; +struct Local1(Rc); + +impl Remote1 for Box> {} +impl Remote1> for Box> {} +impl Remote1> for Box> {} +impl Remote1>> for Box> {} + +fn main() {} diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs b/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs index af5e8f49754e..78bd549ba791 100644 --- a/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs +++ b/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs @@ -1,6 +1,6 @@ use std::marker::PhantomData; struct B(PhantomData<[T; N]>); //~ ERROR const generics are unstable -//~^ ERROR const parameters cannot depend on type parameters +//~^ ERROR the types of const generic parameters must derive `PartialEq` and `Eq` fn main() {} diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr b/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr index c659074a091c..a2872ab982da 100644 --- a/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr +++ b/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr @@ -1,9 +1,3 @@ -error[E0671]: const parameters cannot depend on type parameters - --> $DIR/const-param-type-depends-on-type-param-ungated.rs:3:22 - | -LL | struct B(PhantomData<[T; N]>); - | ^ const parameter depends on type parameter - error[E0658]: const generics are unstable --> $DIR/const-param-type-depends-on-type-param-ungated.rs:3:19 | @@ -13,7 +7,13 @@ LL | struct B(PhantomData<[T; N]>); = note: for more information, see https://github.com/rust-lang/rust/issues/44580 = help: add `#![feature(const_generics)]` to the crate attributes to enable +error[E0741]: the types of const generic parameters must derive `PartialEq` and `Eq` + --> $DIR/const-param-type-depends-on-type-param-ungated.rs:3:22 + | +LL | struct B(PhantomData<[T; N]>); + | ^ `T` doesn't derive both `PartialEq` and `Eq` + error: aborting due to 2 previous errors -Some errors have detailed explanations: E0658, E0671. +Some errors have detailed explanations: E0658, E0741. For more information about an error, try `rustc --explain E0658`. diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param.rs b/src/test/ui/const-generics/const-param-type-depends-on-type-param.rs index 28e0d6c2bb7e..b76209571b05 100644 --- a/src/test/ui/const-generics/const-param-type-depends-on-type-param.rs +++ b/src/test/ui/const-generics/const-param-type-depends-on-type-param.rs @@ -7,7 +7,6 @@ // details. pub struct Dependent([(); X]); -//~^ ERROR const parameters cannot depend on type parameters -//~^^ ERROR parameter `T` is never used +//~^ ERROR the types of const generic parameters must derive `PartialEq` and `Eq` fn main() {} diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr b/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr index db14f9c9bf69..c9d6db7e2c22 100644 --- a/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr +++ b/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr @@ -1,9 +1,3 @@ -error[E0671]: const parameters cannot depend on type parameters - --> $DIR/const-param-type-depends-on-type-param.rs:9:34 - | -LL | pub struct Dependent([(); X]); - | ^ const parameter depends on type parameter - warning: the feature `const_generics` is incomplete and may cause the compiler to crash --> $DIR/const-param-type-depends-on-type-param.rs:1:12 | @@ -12,15 +6,12 @@ LL | #![feature(const_generics)] | = note: `#[warn(incomplete_features)]` on by default -error[E0392]: parameter `T` is never used - --> $DIR/const-param-type-depends-on-type-param.rs:9:22 +error[E0741]: the types of const generic parameters must derive `PartialEq` and `Eq` + --> $DIR/const-param-type-depends-on-type-param.rs:9:34 | LL | pub struct Dependent([(); X]); - | ^ unused parameter - | - = help: consider removing `T`, referring to it in a field, or using a marker such as `std::marker::PhantomData` + | ^ `T` doesn't derive both `PartialEq` and `Eq` -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0392, E0671. -For more information about an error, try `rustc --explain E0392`. +For more information about this error, try `rustc --explain E0741`. diff --git a/src/test/ui/const-generics/forbid-non-structural_match-types.rs b/src/test/ui/const-generics/forbid-non-structural_match-types.rs new file mode 100644 index 000000000000..7bc4f3986eb7 --- /dev/null +++ b/src/test/ui/const-generics/forbid-non-structural_match-types.rs @@ -0,0 +1,13 @@ +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +#[derive(PartialEq, Eq)] +struct A; + +struct B; // ok + +struct C; + +struct D; //~ ERROR the types of const generic parameters must derive + +fn main() {} diff --git a/src/test/ui/const-generics/forbid-non-structural_match-types.stderr b/src/test/ui/const-generics/forbid-non-structural_match-types.stderr new file mode 100644 index 000000000000..0fd9e0599e80 --- /dev/null +++ b/src/test/ui/const-generics/forbid-non-structural_match-types.stderr @@ -0,0 +1,17 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/forbid-non-structural_match-types.rs:1:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +error[E0741]: the types of const generic parameters must derive `PartialEq` and `Eq` + --> $DIR/forbid-non-structural_match-types.rs:11:19 + | +LL | struct D; + | ^ `C` doesn't derive both `PartialEq` and `Eq` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0741`. diff --git a/src/test/ui/const-generics/issues/issue-62579-no-match.rs b/src/test/ui/const-generics/issues/issue-62579-no-match.rs new file mode 100644 index 000000000000..0ff7ddc41fe4 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-62579-no-match.rs @@ -0,0 +1,15 @@ +// run-pass + +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +#[derive(PartialEq, Eq)] +struct NoMatch; + +fn foo() -> bool { + true +} + +fn main() { + foo::<{NoMatch}>(); +} diff --git a/src/test/ui/const-generics/issues/issue-62579-no-match.stderr b/src/test/ui/const-generics/issues/issue-62579-no-match.stderr new file mode 100644 index 000000000000..759d5fdeb4c1 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-62579-no-match.stderr @@ -0,0 +1,8 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/issue-62579-no-match.rs:3:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + diff --git a/src/test/ui/const-generics/issues/issue-65675.rs b/src/test/ui/const-generics/issues/issue-65675.rs new file mode 100644 index 000000000000..3ca527313f93 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-65675.rs @@ -0,0 +1,10 @@ +// run-pass +// compile-flags: -Z chalk + +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +pub struct Foo([T; N]); +impl Foo {} + +fn main() {} diff --git a/src/test/ui/const-generics/issues/issue-65675.stderr b/src/test/ui/const-generics/issues/issue-65675.stderr new file mode 100644 index 000000000000..60b388e62783 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-65675.stderr @@ -0,0 +1,8 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/issue-65675.rs:4:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + diff --git a/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.rs b/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.rs new file mode 100644 index 000000000000..8945360b7be6 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.rs @@ -0,0 +1,41 @@ +// Test that the use of the non object-safe trait objects +// are gated by `object_safe_for_dispatch` feature gate. + +trait NonObjectSafe1: Sized {} + +trait NonObjectSafe2 { + fn static_fn() {} +} + +trait NonObjectSafe3 { + fn foo(&self); +} + +trait NonObjectSafe4 { + fn foo(&self, &Self); +} + +fn takes_non_object_safe_ref(obj: &dyn NonObjectSafe1) { + //~^ ERROR E0038 +} + +fn return_non_object_safe_ref() -> &'static dyn NonObjectSafe2 { + //~^ ERROR E0038 + loop {} +} + +fn takes_non_object_safe_box(obj: Box) { + //~^ ERROR E0038 +} + +fn return_non_object_safe_rc() -> std::rc::Rc { + //~^ ERROR E0038 + loop {} +} + +trait Trait {} + +impl Trait for dyn NonObjectSafe1 {} +//~^ ERROR E0038 + +fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr b/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr new file mode 100644 index 000000000000..54e64e2fc1bd --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr @@ -0,0 +1,46 @@ +error[E0038]: the trait `NonObjectSafe1` cannot be made into an object + --> $DIR/feature-gate-object_safe_for_dispatch.rs:18:1 + | +LL | fn takes_non_object_safe_ref(obj: &dyn NonObjectSafe1) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NonObjectSafe1` cannot be made into an object + | + = note: the trait cannot require that `Self : Sized` + +error[E0038]: the trait `NonObjectSafe2` cannot be made into an object + --> $DIR/feature-gate-object_safe_for_dispatch.rs:22:1 + | +LL | fn static_fn() {} + | --------- associated function `static_fn` has no `self` parameter +... +LL | fn return_non_object_safe_ref() -> &'static dyn NonObjectSafe2 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NonObjectSafe2` cannot be made into an object + +error[E0038]: the trait `NonObjectSafe3` cannot be made into an object + --> $DIR/feature-gate-object_safe_for_dispatch.rs:27:1 + | +LL | fn foo(&self); + | --- method `foo` has generic type parameters +... +LL | fn takes_non_object_safe_box(obj: Box) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NonObjectSafe3` cannot be made into an object + +error[E0038]: the trait `NonObjectSafe4` cannot be made into an object + --> $DIR/feature-gate-object_safe_for_dispatch.rs:31:1 + | +LL | fn foo(&self, &Self); + | --- method `foo` references the `Self` type in its parameters or return type +... +LL | fn return_non_object_safe_rc() -> std::rc::Rc { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NonObjectSafe4` cannot be made into an object + +error[E0038]: the trait `NonObjectSafe1` cannot be made into an object + --> $DIR/feature-gate-object_safe_for_dispatch.rs:38:6 + | +LL | impl Trait for dyn NonObjectSafe1 {} + | ^^^^^ the trait `NonObjectSafe1` cannot be made into an object + | + = note: the trait cannot require that `Self : Sized` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/fmt/format-string-error.rs b/src/test/ui/fmt/format-string-error.rs index cca949aab636..691c06a2402c 100644 --- a/src/test/ui/fmt/format-string-error.rs +++ b/src/test/ui/fmt/format-string-error.rs @@ -48,4 +48,6 @@ fn main() { "###); //~^^^ ERROR invalid format string: unmatched `}` found + println!("{} {} {}", 1, 2); + //~^ ERROR 3 positional arguments in format string, but there are 2 arguments } diff --git a/src/test/ui/fmt/format-string-error.stderr b/src/test/ui/fmt/format-string-error.stderr index 3dc122a7399d..32119b18774b 100644 --- a/src/test/ui/fmt/format-string-error.stderr +++ b/src/test/ui/fmt/format-string-error.stderr @@ -107,5 +107,11 @@ LL | } | = note: if you intended to print `}`, you can escape it using `}}` -error: aborting due to 12 previous errors +error: 3 positional arguments in format string, but there are 2 arguments + --> $DIR/format-string-error.rs:51:15 + | +LL | println!("{} {} {}", 1, 2); + | ^^ ^^ ^^ - - + +error: aborting due to 13 previous errors diff --git a/src/test/ui/if/ifmt-bad-arg.stderr b/src/test/ui/if/ifmt-bad-arg.stderr index 336ea2254bf5..c58cbc312335 100644 --- a/src/test/ui/if/ifmt-bad-arg.stderr +++ b/src/test/ui/if/ifmt-bad-arg.stderr @@ -224,8 +224,9 @@ error: 4 positional arguments in format string, but there are 3 arguments --> $DIR/ifmt-bad-arg.rs:78:15 | LL | println!("{} {:.*} {}", 1, 3.2, 4); - | ^^ ^^--^ ^^ --- this parameter corresponds to the precision flag - | | + | ^^ ^^--^ ^^ - --- - + | | | + | | this parameter corresponds to the precision flag | this precision flag adds an extra required argument at position 1, which is why there are 4 arguments expected | = note: positional arguments are zero-based @@ -235,8 +236,9 @@ error: 4 positional arguments in format string, but there are 3 arguments --> $DIR/ifmt-bad-arg.rs:81:15 | LL | println!("{} {:07$.*} {}", 1, 3.2, 4); - | ^^ ^^^----^ ^^ --- this parameter corresponds to the precision flag - | | | + | ^^ ^^^----^ ^^ - --- - + | | | | + | | | this parameter corresponds to the precision flag | | this precision flag adds an extra required argument at position 1, which is why there are 4 arguments expected | this width flag expects an `usize` argument at position 7, but there are 3 arguments | diff --git a/src/test/ui/intrinsics/intrinsic-alignment.rs b/src/test/ui/intrinsics/intrinsic-alignment.rs index 6a67d04a54cf..02e3139d2944 100644 --- a/src/test/ui/intrinsics/intrinsic-alignment.rs +++ b/src/test/ui/intrinsics/intrinsic-alignment.rs @@ -19,7 +19,8 @@ mod rusti { target_os = "macos", target_os = "netbsd", target_os = "openbsd", - target_os = "solaris"))] + target_os = "solaris", + target_os = "vxworks"))] mod m { #[main] #[cfg(target_arch = "x86")] diff --git a/src/test/ui/issues/issue-19538.stderr b/src/test/ui/issues/issue-19538.stderr index 5415a45f7d62..83c03b514ddc 100644 --- a/src/test/ui/issues/issue-19538.stderr +++ b/src/test/ui/issues/issue-19538.stderr @@ -17,6 +17,7 @@ LL | let test: &mut dyn Bar = &mut thing; | ^^^^^^^^^^ the trait `Bar` cannot be made into an object | = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&mut dyn Bar>` for `&mut Thing` + = note: required by cast to type `&mut dyn Bar` error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-20692.stderr b/src/test/ui/issues/issue-20692.stderr index 66309394a426..06c83f65be26 100644 --- a/src/test/ui/issues/issue-20692.stderr +++ b/src/test/ui/issues/issue-20692.stderr @@ -14,6 +14,7 @@ LL | let _ = x | = note: the trait cannot require that `Self : Sized` = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Array>` for `&T` + = note: required by cast to type `&dyn Array` error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-38604.stderr b/src/test/ui/issues/issue-38604.stderr index 8ef7d346cb33..8b923a2c6b23 100644 --- a/src/test/ui/issues/issue-38604.stderr +++ b/src/test/ui/issues/issue-38604.stderr @@ -14,6 +14,7 @@ LL | Box::new(()); | = note: the trait cannot use `Self` as a type parameter in the supertraits or where-clauses = note: required because of the requirements on the impl of `std::ops::CoerceUnsized>` for `std::boxed::Box<()>` + = note: required by cast to type `std::boxed::Box` error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-65611.rs b/src/test/ui/issues/issue-65611.rs new file mode 100644 index 000000000000..b74ee1b0c6e5 --- /dev/null +++ b/src/test/ui/issues/issue-65611.rs @@ -0,0 +1,63 @@ +use std::mem::MaybeUninit; +use std::ops::Deref; + +pub unsafe trait Array { + /// The array’s element type + type Item; + #[doc(hidden)] + /// The smallest index type that indexes the array. + type Index: Index; + #[doc(hidden)] + fn as_ptr(&self) -> *const Self::Item; + #[doc(hidden)] + fn as_mut_ptr(&mut self) -> *mut Self::Item; + #[doc(hidden)] + fn capacity() -> usize; +} + +pub trait Index : PartialEq + Copy { + fn to_usize(self) -> usize; + fn from(usize) -> Self; +} + +impl Index for usize { + fn to_usize(self) -> usize { self } + fn from(val: usize) -> Self { + val + } +} + +unsafe impl Array for [T; 1] { + type Item = T; + type Index = usize; + fn as_ptr(&self) -> *const T { self as *const _ as *const _ } + fn as_mut_ptr(&mut self) -> *mut T { self as *mut _ as *mut _} + fn capacity() -> usize { 1 } +} + +impl Deref for ArrayVec { + type Target = [A::Item]; + #[inline] + fn deref(&self) -> &[A::Item] { + panic!() + } +} + +pub struct ArrayVec { + xs: MaybeUninit, + len: usize, +} + +impl ArrayVec { + pub fn new() -> ArrayVec { + panic!() + } +} + +fn main() { + let mut buffer = ArrayVec::new(); + let x = buffer.last().unwrap().0.clone(); + //~^ ERROR type annotations needed + //~| ERROR no field `0` on type `&_` + buffer.reverse(); +} diff --git a/src/test/ui/issues/issue-65611.stderr b/src/test/ui/issues/issue-65611.stderr new file mode 100644 index 000000000000..cb441c13c6b9 --- /dev/null +++ b/src/test/ui/issues/issue-65611.stderr @@ -0,0 +1,18 @@ +error[E0282]: type annotations needed + --> $DIR/issue-65611.rs:59:20 + | +LL | let x = buffer.last().unwrap().0.clone(); + | ^^^^ cannot infer type for `T` + | + = note: type must be known at this point + +error[E0609]: no field `0` on type `&_` + --> $DIR/issue-65611.rs:59:36 + | +LL | let x = buffer.last().unwrap().0.clone(); + | ^ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0282, E0609. +For more information about an error, try `rustc --explain E0282`. diff --git a/src/test/ui/kindck/kindck-inherited-copy-bound.stderr b/src/test/ui/kindck/kindck-inherited-copy-bound.curr.stderr similarity index 86% rename from src/test/ui/kindck/kindck-inherited-copy-bound.stderr rename to src/test/ui/kindck/kindck-inherited-copy-bound.curr.stderr index 27901d069279..a93f4686496a 100644 --- a/src/test/ui/kindck/kindck-inherited-copy-bound.stderr +++ b/src/test/ui/kindck/kindck-inherited-copy-bound.curr.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `std::boxed::Box<{integer}>: std::marker::Copy` is not satisfied - --> $DIR/kindck-inherited-copy-bound.rs:18:16 + --> $DIR/kindck-inherited-copy-bound.rs:21:16 | LL | fn take_param(foo: &T) { } | ---------- --- required by this bound in `take_param` @@ -10,7 +10,7 @@ LL | take_param(&x); = note: required because of the requirements on the impl of `Foo` for `std::boxed::Box<{integer}>` error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/kindck-inherited-copy-bound.rs:24:19 + --> $DIR/kindck-inherited-copy-bound.rs:28:19 | LL | let z = &x as &dyn Foo; | ^^^^^^^^ the trait `Foo` cannot be made into an object @@ -18,13 +18,14 @@ LL | let z = &x as &dyn Foo; = note: the trait cannot require that `Self : Sized` error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/kindck-inherited-copy-bound.rs:24:13 + --> $DIR/kindck-inherited-copy-bound.rs:28:13 | LL | let z = &x as &dyn Foo; | ^^ the trait `Foo` cannot be made into an object | = note: the trait cannot require that `Self : Sized` = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Foo>` for `&std::boxed::Box<{integer}>` + = note: required by cast to type `&dyn Foo` error: aborting due to 3 previous errors diff --git a/src/test/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr b/src/test/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr new file mode 100644 index 000000000000..7c67c5f9e959 --- /dev/null +++ b/src/test/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr @@ -0,0 +1,25 @@ +error[E0277]: the trait bound `std::boxed::Box<{integer}>: std::marker::Copy` is not satisfied + --> $DIR/kindck-inherited-copy-bound.rs:21:16 + | +LL | fn take_param(foo: &T) { } + | ---------- --- required by this bound in `take_param` +... +LL | take_param(&x); + | ^^ the trait `std::marker::Copy` is not implemented for `std::boxed::Box<{integer}>` + | + = note: required because of the requirements on the impl of `Foo` for `std::boxed::Box<{integer}>` + +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/kindck-inherited-copy-bound.rs:28:13 + | +LL | let z = &x as &dyn Foo; + | ^^ the trait `Foo` cannot be made into an object + | + = note: the trait cannot require that `Self : Sized` + = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Foo>` for `&std::boxed::Box` + = note: required by cast to type `&dyn Foo` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0038, E0277. +For more information about an error, try `rustc --explain E0038`. diff --git a/src/test/ui/kindck/kindck-inherited-copy-bound.rs b/src/test/ui/kindck/kindck-inherited-copy-bound.rs index 61e72908248d..aad693e5b193 100644 --- a/src/test/ui/kindck/kindck-inherited-copy-bound.rs +++ b/src/test/ui/kindck/kindck-inherited-copy-bound.rs @@ -1,5 +1,8 @@ // Test that Copy bounds inherited by trait are checked. +// +// revisions: curr object_safe_for_dispatch +#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] #![feature(box_syntax)] use std::any::Any; @@ -15,15 +18,17 @@ fn take_param(foo: &T) { } fn a() { let x: Box<_> = box 3; - take_param(&x); //~ ERROR E0277 + take_param(&x); //[curr]~ ERROR E0277 + //[object_safe_for_dispatch]~^ ERROR E0277 } fn b() { let x: Box<_> = box 3; let y = &x; let z = &x as &dyn Foo; - //~^ ERROR E0038 - //~| ERROR E0038 + //[curr]~^ ERROR E0038 + //[curr]~| ERROR E0038 + //[object_safe_for_dispatch]~^^^ ERROR E0038 } fn main() { } diff --git a/src/test/ui/lint/unused_parens_json_suggestion.fixed b/src/test/ui/lint/unused_parens_json_suggestion.fixed index 427407119102..15ee19755bff 100644 --- a/src/test/ui/lint/unused_parens_json_suggestion.fixed +++ b/src/test/ui/lint/unused_parens_json_suggestion.fixed @@ -1,5 +1,4 @@ -// compile-flags: --error-format pretty-json -Zunstable-options -// build-pass (FIXME(62277): could be check-pass?) +// compile-flags: --error-format json -Zunstable-options // run-rustfix // The output for humans should just highlight the whole span without showing @@ -8,13 +7,13 @@ // stripping away any starting or ending parenthesis characters—hence this // test of the JSON error format. -#![warn(unused_parens)] +#![deny(unused_parens)] #![allow(unreachable_code)] fn main() { // We want to suggest the properly-balanced expression `1 / (2 + 3)`, not // the malformed `1 / (2 + 3` - let _a = 1 / (2 + 3); + let _a = 1 / (2 + 3); //~ERROR unnecessary parentheses f(); } diff --git a/src/test/ui/lint/unused_parens_json_suggestion.rs b/src/test/ui/lint/unused_parens_json_suggestion.rs index 87192503986c..d72df21e09ae 100644 --- a/src/test/ui/lint/unused_parens_json_suggestion.rs +++ b/src/test/ui/lint/unused_parens_json_suggestion.rs @@ -1,5 +1,4 @@ -// compile-flags: --error-format pretty-json -Zunstable-options -// build-pass (FIXME(62277): could be check-pass?) +// compile-flags: --error-format json -Zunstable-options // run-rustfix // The output for humans should just highlight the whole span without showing @@ -8,13 +7,13 @@ // stripping away any starting or ending parenthesis characters—hence this // test of the JSON error format. -#![warn(unused_parens)] +#![deny(unused_parens)] #![allow(unreachable_code)] fn main() { // We want to suggest the properly-balanced expression `1 / (2 + 3)`, not // the malformed `1 / (2 + 3` - let _a = (1 / (2 + 3)); + let _a = (1 / (2 + 3)); //~ERROR unnecessary parentheses f(); } diff --git a/src/test/ui/lint/unused_parens_json_suggestion.stderr b/src/test/ui/lint/unused_parens_json_suggestion.stderr index 256c7555c908..c503c100808d 100644 --- a/src/test/ui/lint/unused_parens_json_suggestion.stderr +++ b/src/test/ui/lint/unused_parens_json_suggestion.stderr @@ -1,106 +1,16 @@ -{ - "message": "unnecessary parentheses around assigned value", - "code": { - "code": "unused_parens", - "explanation": null - }, - "level": "warning", - "spans": [ - { - "file_name": "$DIR/unused_parens_json_suggestion.rs", - "byte_start": 654, - "byte_end": 667, - "line_start": 17, - "line_end": 17, - "column_start": 14, - "column_end": 27, - "is_primary": true, - "text": [ - { - "text": " let _a = (1 / (2 + 3));", - "highlight_start": 14, - "highlight_end": 27 - } - ], - "label": null, - "suggested_replacement": null, - "suggestion_applicability": null, - "expansion": null - } - ], - "children": [ - { - "message": "lint level defined here", - "code": null, - "level": "note", - "spans": [ - { - "file_name": "$DIR/unused_parens_json_suggestion.rs", - "byte_start": 472, - "byte_end": 485, - "line_start": 11, - "line_end": 11, - "column_start": 9, - "column_end": 22, - "is_primary": true, - "text": [ - { - "text": "#![warn(unused_parens)]", - "highlight_start": 9, - "highlight_end": 22 - } - ], - "label": null, - "suggested_replacement": null, - "suggestion_applicability": null, - "expansion": null - } - ], - "children": [], - "rendered": null - }, - { - "message": "remove these parentheses", - "code": null, - "level": "help", - "spans": [ - { - "file_name": "$DIR/unused_parens_json_suggestion.rs", - "byte_start": 654, - "byte_end": 667, - "line_start": 17, - "line_end": 17, - "column_start": 14, - "column_end": 27, - "is_primary": true, - "text": [ - { - "text": " let _a = (1 / (2 + 3));", - "highlight_start": 14, - "highlight_end": 27 - } - ], - "label": null, - "suggested_replacement": "1 / (2 + 3)", - "suggestion_applicability": "MachineApplicable", - "expansion": null - } - ], - "children": [], - "rendered": null - } - ], - "rendered": "warning: unnecessary parentheses around assigned value - --> $DIR/unused_parens_json_suggestion.rs:17:14 +{"message":"unnecessary parentheses around assigned value","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":596,"byte_end":609,"line_start":16,"line_end":16,"column_start":14,"column_end":27,"is_primary":true,"text":[{"text":" let _a = (1 / (2 + 3)); + --> $DIR/unused_parens_json_suggestion.rs:16:14 | LL | let _a = (1 / (2 + 3)); | ^^^^^^^^^^^^^ help: remove these parentheses | note: lint level defined here - --> $DIR/unused_parens_json_suggestion.rs:11:9 + --> $DIR/unused_parens_json_suggestion.rs:10:9 | -LL | #![warn(unused_parens)] +LL | #![deny(unused_parens)] | ^^^^^^^^^^^^^ -" -} +"} +{"message":"aborting due to previous error","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to previous error + +"} diff --git a/src/test/ui/lint/unused_parens_remove_json_suggestion.fixed b/src/test/ui/lint/unused_parens_remove_json_suggestion.fixed index 2459eb1ac5cb..1d891d328dd5 100644 --- a/src/test/ui/lint/unused_parens_remove_json_suggestion.fixed +++ b/src/test/ui/lint/unused_parens_remove_json_suggestion.fixed @@ -1,5 +1,4 @@ -// compile-flags: --error-format pretty-json -Zunstable-options -// build-pass +// compile-flags: --error-format json -Zunstable-options // run-rustfix // The output for humans should just highlight the whole span without showing @@ -8,14 +7,14 @@ // stripping away any starting or ending parenthesis characters—hence this // test of the JSON error format. -#![warn(unused_parens)] +#![deny(unused_parens)] #![allow(unreachable_code)] fn main() { let _b = false; - if _b { + if _b { //~ ERROR unnecessary parentheses println!("hello"); } @@ -26,29 +25,29 @@ fn main() { fn f() -> bool { let c = false; - if c { + if c { //~ ERROR unnecessary parentheses println!("next"); } - if c { + if c { //~ ERROR unnecessary parentheses println!("prev"); } while false && true { - if c { + if c { //~ ERROR unnecessary parentheses println!("norm"); } } - while true && false { - for _ in 0 .. 3 { + while true && false { //~ ERROR unnecessary parentheses + for _ in 0 .. 3 { //~ ERROR unnecessary parentheses println!("e~") } } - for _ in 0 .. 3 { - while true && false { + for _ in 0 .. 3 { //~ ERROR unnecessary parentheses + while true && false { //~ ERROR unnecessary parentheses println!("e~") } } diff --git a/src/test/ui/lint/unused_parens_remove_json_suggestion.rs b/src/test/ui/lint/unused_parens_remove_json_suggestion.rs index 0e9869b67d59..494cd1845063 100644 --- a/src/test/ui/lint/unused_parens_remove_json_suggestion.rs +++ b/src/test/ui/lint/unused_parens_remove_json_suggestion.rs @@ -1,5 +1,4 @@ -// compile-flags: --error-format pretty-json -Zunstable-options -// build-pass +// compile-flags: --error-format json -Zunstable-options // run-rustfix // The output for humans should just highlight the whole span without showing @@ -8,14 +7,14 @@ // stripping away any starting or ending parenthesis characters—hence this // test of the JSON error format. -#![warn(unused_parens)] +#![deny(unused_parens)] #![allow(unreachable_code)] fn main() { let _b = false; - if (_b) { + if (_b) { //~ ERROR unnecessary parentheses println!("hello"); } @@ -26,29 +25,29 @@ fn main() { fn f() -> bool { let c = false; - if(c) { + if(c) { //~ ERROR unnecessary parentheses println!("next"); } - if (c){ + if (c){ //~ ERROR unnecessary parentheses println!("prev"); } while (false && true){ - if (c) { + if (c) { //~ ERROR unnecessary parentheses println!("norm"); } } - while(true && false) { - for _ in (0 .. 3){ + while(true && false) { //~ ERROR unnecessary parentheses + for _ in (0 .. 3){ //~ ERROR unnecessary parentheses println!("e~") } } - for _ in (0 .. 3) { - while (true && false) { + for _ in (0 .. 3) { //~ ERROR unnecessary parentheses + while (true && false) { //~ ERROR unnecessary parentheses println!("e~") } } diff --git a/src/test/ui/lint/unused_parens_remove_json_suggestion.stderr b/src/test/ui/lint/unused_parens_remove_json_suggestion.stderr index b4eab200dd01..873f105435e0 100644 --- a/src/test/ui/lint/unused_parens_remove_json_suggestion.stderr +++ b/src/test/ui/lint/unused_parens_remove_json_suggestion.stderr @@ -1,666 +1,72 @@ -{ - "message": "unnecessary parentheses around `if` condition", - "code": { - "code": "unused_parens", - "explanation": null - }, - "level": "warning", - "spans": [ - { - "file_name": "$DIR/unused_parens_remove_json_suggestion.rs", - "byte_start": 521, - "byte_end": 525, - "line_start": 18, - "line_end": 18, - "column_start": 8, - "column_end": 12, - "is_primary": true, - "text": [ - { - "text": " if (_b) {", - "highlight_start": 8, - "highlight_end": 12 - } - ], - "label": null, - "suggested_replacement": null, - "suggestion_applicability": null, - "expansion": null - } - ], - "children": [ - { - "message": "lint level defined here", - "code": null, - "level": "note", - "spans": [ - { - "file_name": "$DIR/unused_parens_remove_json_suggestion.rs", - "byte_start": 435, - "byte_end": 448, - "line_start": 11, - "line_end": 11, - "column_start": 9, - "column_end": 22, - "is_primary": true, - "text": [ - { - "text": "#![warn(unused_parens)]", - "highlight_start": 9, - "highlight_end": 22 - } - ], - "label": null, - "suggested_replacement": null, - "suggestion_applicability": null, - "expansion": null - } - ], - "children": [], - "rendered": null - }, - { - "message": "remove these parentheses", - "code": null, - "level": "help", - "spans": [ - { - "file_name": "$DIR/unused_parens_remove_json_suggestion.rs", - "byte_start": 521, - "byte_end": 525, - "line_start": 18, - "line_end": 18, - "column_start": 8, - "column_end": 12, - "is_primary": true, - "text": [ - { - "text": " if (_b) {", - "highlight_start": 8, - "highlight_end": 12 - } - ], - "label": null, - "suggested_replacement": "_b", - "suggestion_applicability": "MachineApplicable", - "expansion": null - } - ], - "children": [], - "rendered": null - } - ], - "rendered": "warning: unnecessary parentheses around `if` condition - --> $DIR/unused_parens_remove_json_suggestion.rs:18:8 +{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":500,"byte_end":504,"line_start":17,"line_end":17,"column_start":8,"column_end":12,"is_primary":true,"text":[{"text":" if (_b) { + --> $DIR/unused_parens_remove_json_suggestion.rs:17:8 | LL | if (_b) { | ^^^^ help: remove these parentheses | note: lint level defined here - --> $DIR/unused_parens_remove_json_suggestion.rs:11:9 + --> $DIR/unused_parens_remove_json_suggestion.rs:10:9 | -LL | #![warn(unused_parens)] +LL | #![deny(unused_parens)] | ^^^^^^^^^^^^^ -" -} -{ - "message": "unnecessary parentheses around `if` condition", - "code": { - "code": "unused_parens", - "explanation": null - }, - "level": "warning", - "spans": [ - { - "file_name": "$DIR/unused_parens_remove_json_suggestion.rs", - "byte_start": 618, - "byte_end": 621, - "line_start": 29, - "line_end": 29, - "column_start": 7, - "column_end": 10, - "is_primary": true, - "text": [ - { - "text": " if(c) {", - "highlight_start": 7, - "highlight_end": 10 - } - ], - "label": null, - "suggested_replacement": null, - "suggestion_applicability": null, - "expansion": null - } - ], - "children": [ - { - "message": "remove these parentheses", - "code": null, - "level": "help", - "spans": [ - { - "file_name": "$DIR/unused_parens_remove_json_suggestion.rs", - "byte_start": 618, - "byte_end": 621, - "line_start": 29, - "line_end": 29, - "column_start": 7, - "column_end": 10, - "is_primary": true, - "text": [ - { - "text": " if(c) {", - "highlight_start": 7, - "highlight_end": 10 - } - ], - "label": null, - "suggested_replacement": " c", - "suggestion_applicability": "MachineApplicable", - "expansion": null - } - ], - "children": [], - "rendered": null - } - ], - "rendered": "warning: unnecessary parentheses around `if` condition - --> $DIR/unused_parens_remove_json_suggestion.rs:29:7 +"} +{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":631,"byte_end":634,"line_start":28,"line_end":28,"column_start":7,"column_end":10,"is_primary":true,"text":[{"text":" if(c) { + --> $DIR/unused_parens_remove_json_suggestion.rs:28:7 | LL | if(c) { | ^^^ help: remove these parentheses -" -} -{ - "message": "unnecessary parentheses around `if` condition", - "code": { - "code": "unused_parens", - "explanation": null - }, - "level": "warning", - "spans": [ - { - "file_name": "$DIR/unused_parens_remove_json_suggestion.rs", - "byte_start": 664, - "byte_end": 667, - "line_start": 33, - "line_end": 33, - "column_start": 8, - "column_end": 11, - "is_primary": true, - "text": [ - { - "text": " if (c){", - "highlight_start": 8, - "highlight_end": 11 - } - ], - "label": null, - "suggested_replacement": null, - "suggestion_applicability": null, - "expansion": null - } - ], - "children": [ - { - "message": "remove these parentheses", - "code": null, - "level": "help", - "spans": [ - { - "file_name": "$DIR/unused_parens_remove_json_suggestion.rs", - "byte_start": 664, - "byte_end": 667, - "line_start": 33, - "line_end": 33, - "column_start": 8, - "column_end": 11, - "is_primary": true, - "text": [ - { - "text": " if (c){", - "highlight_start": 8, - "highlight_end": 11 - } - ], - "label": null, - "suggested_replacement": "c ", - "suggestion_applicability": "MachineApplicable", - "expansion": null - } - ], - "children": [], - "rendered": null - } - ], - "rendered": "warning: unnecessary parentheses around `if` condition - --> $DIR/unused_parens_remove_json_suggestion.rs:33:8 +"} +{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":711,"byte_end":714,"line_start":32,"line_end":32,"column_start":8,"column_end":11,"is_primary":true,"text":[{"text":" if (c){ + --> $DIR/unused_parens_remove_json_suggestion.rs:32:8 | LL | if (c){ | ^^^ help: remove these parentheses -" -} -{ - "message": "unnecessary parentheses around `while` condition", - "code": { - "code": "unused_parens", - "explanation": null - }, - "level": "warning", - "spans": [ - { - "file_name": "$DIR/unused_parens_remove_json_suggestion.rs", - "byte_start": 712, - "byte_end": 727, - "line_start": 37, - "line_end": 37, - "column_start": 11, - "column_end": 26, - "is_primary": true, - "text": [ - { - "text": " while (false && true){", - "highlight_start": 11, - "highlight_end": 26 - } - ], - "label": null, - "suggested_replacement": null, - "suggestion_applicability": null, - "expansion": null - } - ], - "children": [ - { - "message": "remove these parentheses", - "code": null, - "level": "help", - "spans": [ - { - "file_name": "$DIR/unused_parens_remove_json_suggestion.rs", - "byte_start": 712, - "byte_end": 727, - "line_start": 37, - "line_end": 37, - "column_start": 11, - "column_end": 26, - "is_primary": true, - "text": [ - { - "text": " while (false && true){", - "highlight_start": 11, - "highlight_end": 26 - } - ], - "label": null, - "suggested_replacement": "false && true ", - "suggestion_applicability": "MachineApplicable", - "expansion": null - } - ], - "children": [], - "rendered": null - } - ], - "rendered": "warning: unnecessary parentheses around `while` condition - --> $DIR/unused_parens_remove_json_suggestion.rs:37:11 +"} +{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":793,"byte_end":808,"line_start":36,"line_end":36,"column_start":11,"column_end":26,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":11,"highlight_end":26}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":793,"byte_end":808,"line_start":36,"line_end":36,"column_start":11,"column_end":26,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":11,"highlight_end":26}],"label":null,"suggested_replacement":"false && true ","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `while` condition + --> $DIR/unused_parens_remove_json_suggestion.rs:36:11 | LL | while (false && true){ | ^^^^^^^^^^^^^^^ help: remove these parentheses -" -} -{ - "message": "unnecessary parentheses around `if` condition", - "code": { - "code": "unused_parens", - "explanation": null - }, - "level": "warning", - "spans": [ - { - "file_name": "$DIR/unused_parens_remove_json_suggestion.rs", - "byte_start": 740, - "byte_end": 743, - "line_start": 38, - "line_end": 38, - "column_start": 12, - "column_end": 15, - "is_primary": true, - "text": [ - { - "text": " if (c) {", - "highlight_start": 12, - "highlight_end": 15 - } - ], - "label": null, - "suggested_replacement": null, - "suggestion_applicability": null, - "expansion": null - } - ], - "children": [ - { - "message": "remove these parentheses", - "code": null, - "level": "help", - "spans": [ - { - "file_name": "$DIR/unused_parens_remove_json_suggestion.rs", - "byte_start": 740, - "byte_end": 743, - "line_start": 38, - "line_end": 38, - "column_start": 12, - "column_end": 15, - "is_primary": true, - "text": [ - { - "text": " if (c) {", - "highlight_start": 12, - "highlight_end": 15 - } - ], - "label": null, - "suggested_replacement": "c", - "suggestion_applicability": "MachineApplicable", - "expansion": null - } - ], - "children": [], - "rendered": null - } - ], - "rendered": "warning: unnecessary parentheses around `if` condition - --> $DIR/unused_parens_remove_json_suggestion.rs:38:12 +"} +{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":821,"byte_end":824,"line_start":37,"line_end":37,"column_start":12,"column_end":15,"is_primary":true,"text":[{"text":" if (c) { + --> $DIR/unused_parens_remove_json_suggestion.rs:37:12 | LL | if (c) { | ^^^ help: remove these parentheses -" -} -{ - "message": "unnecessary parentheses around `while` condition", - "code": { - "code": "unused_parens", - "explanation": null - }, - "level": "warning", - "spans": [ - { - "file_name": "$DIR/unused_parens_remove_json_suggestion.rs", - "byte_start": 803, - "byte_end": 818, - "line_start": 44, - "line_end": 44, - "column_start": 10, - "column_end": 25, - "is_primary": true, - "text": [ - { - "text": " while(true && false) {", - "highlight_start": 10, - "highlight_end": 25 - } - ], - "label": null, - "suggested_replacement": null, - "suggestion_applicability": null, - "expansion": null - } - ], - "children": [ - { - "message": "remove these parentheses", - "code": null, - "level": "help", - "spans": [ - { - "file_name": "$DIR/unused_parens_remove_json_suggestion.rs", - "byte_start": 803, - "byte_end": 818, - "line_start": 44, - "line_end": 44, - "column_start": 10, - "column_end": 25, - "is_primary": true, - "text": [ - { - "text": " while(true && false) {", - "highlight_start": 10, - "highlight_end": 25 - } - ], - "label": null, - "suggested_replacement": " true && false", - "suggestion_applicability": "MachineApplicable", - "expansion": null - } - ], - "children": [], - "rendered": null - } - ], - "rendered": "warning: unnecessary parentheses around `while` condition - --> $DIR/unused_parens_remove_json_suggestion.rs:44:10 +"} +{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":918,"byte_end":933,"line_start":43,"line_end":43,"column_start":10,"column_end":25,"is_primary":true,"text":[{"text":" while(true && false) { + --> $DIR/unused_parens_remove_json_suggestion.rs:43:10 | LL | while(true && false) { | ^^^^^^^^^^^^^^^ help: remove these parentheses -" -} -{ - "message": "unnecessary parentheses around `for` head expression", - "code": { - "code": "unused_parens", - "explanation": null - }, - "level": "warning", - "spans": [ - { - "file_name": "$DIR/unused_parens_remove_json_suggestion.rs", - "byte_start": 838, - "byte_end": 846, - "line_start": 45, - "line_end": 45, - "column_start": 18, - "column_end": 26, - "is_primary": true, - "text": [ - { - "text": " for _ in (0 .. 3){", - "highlight_start": 18, - "highlight_end": 26 - } - ], - "label": null, - "suggested_replacement": null, - "suggestion_applicability": null, - "expansion": null - } - ], - "children": [ - { - "message": "remove these parentheses", - "code": null, - "level": "help", - "spans": [ - { - "file_name": "$DIR/unused_parens_remove_json_suggestion.rs", - "byte_start": 838, - "byte_end": 846, - "line_start": 45, - "line_end": 45, - "column_start": 18, - "column_end": 26, - "is_primary": true, - "text": [ - { - "text": " for _ in (0 .. 3){", - "highlight_start": 18, - "highlight_end": 26 - } - ], - "label": null, - "suggested_replacement": "0 .. 3 ", - "suggestion_applicability": "MachineApplicable", - "expansion": null - } - ], - "children": [], - "rendered": null - } - ], - "rendered": "warning: unnecessary parentheses around `for` head expression - --> $DIR/unused_parens_remove_json_suggestion.rs:45:18 +"} +{"message":"unnecessary parentheses around `for` head expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":987,"byte_end":995,"line_start":44,"line_end":44,"column_start":18,"column_end":26,"is_primary":true,"text":[{"text":" for _ in (0 .. 3){ + --> $DIR/unused_parens_remove_json_suggestion.rs:44:18 | LL | for _ in (0 .. 3){ | ^^^^^^^^ help: remove these parentheses -" -} -{ - "message": "unnecessary parentheses around `for` head expression", - "code": { - "code": "unused_parens", - "explanation": null - }, - "level": "warning", - "spans": [ - { - "file_name": "$DIR/unused_parens_remove_json_suggestion.rs", - "byte_start": 905, - "byte_end": 913, - "line_start": 50, - "line_end": 50, - "column_start": 14, - "column_end": 22, - "is_primary": true, - "text": [ - { - "text": " for _ in (0 .. 3) {", - "highlight_start": 14, - "highlight_end": 22 - } - ], - "label": null, - "suggested_replacement": null, - "suggestion_applicability": null, - "expansion": null - } - ], - "children": [ - { - "message": "remove these parentheses", - "code": null, - "level": "help", - "spans": [ - { - "file_name": "$DIR/unused_parens_remove_json_suggestion.rs", - "byte_start": 905, - "byte_end": 913, - "line_start": 50, - "line_end": 50, - "column_start": 14, - "column_end": 22, - "is_primary": true, - "text": [ - { - "text": " for _ in (0 .. 3) {", - "highlight_start": 14, - "highlight_end": 22 - } - ], - "label": null, - "suggested_replacement": "0 .. 3", - "suggestion_applicability": "MachineApplicable", - "expansion": null - } - ], - "children": [], - "rendered": null - } - ], - "rendered": "warning: unnecessary parentheses around `for` head expression - --> $DIR/unused_parens_remove_json_suggestion.rs:50:14 +"} +{"message":"unnecessary parentheses around `for` head expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1088,"byte_end":1096,"line_start":49,"line_end":49,"column_start":14,"column_end":22,"is_primary":true,"text":[{"text":" for _ in (0 .. 3) { + --> $DIR/unused_parens_remove_json_suggestion.rs:49:14 | LL | for _ in (0 .. 3) { | ^^^^^^^^ help: remove these parentheses -" -} -{ - "message": "unnecessary parentheses around `while` condition", - "code": { - "code": "unused_parens", - "explanation": null - }, - "level": "warning", - "spans": [ - { - "file_name": "$DIR/unused_parens_remove_json_suggestion.rs", - "byte_start": 930, - "byte_end": 945, - "line_start": 51, - "line_end": 51, - "column_start": 15, - "column_end": 30, - "is_primary": true, - "text": [ - { - "text": " while (true && false) {", - "highlight_start": 15, - "highlight_end": 30 - } - ], - "label": null, - "suggested_replacement": null, - "suggestion_applicability": null, - "expansion": null - } - ], - "children": [ - { - "message": "remove these parentheses", - "code": null, - "level": "help", - "spans": [ - { - "file_name": "$DIR/unused_parens_remove_json_suggestion.rs", - "byte_start": 930, - "byte_end": 945, - "line_start": 51, - "line_end": 51, - "column_start": 15, - "column_end": 30, - "is_primary": true, - "text": [ - { - "text": " while (true && false) {", - "highlight_start": 15, - "highlight_end": 30 - } - ], - "label": null, - "suggested_replacement": "true && false", - "suggestion_applicability": "MachineApplicable", - "expansion": null - } - ], - "children": [], - "rendered": null - } - ], - "rendered": "warning: unnecessary parentheses around `while` condition - --> $DIR/unused_parens_remove_json_suggestion.rs:51:15 +"} +{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1147,"byte_end":1162,"line_start":50,"line_end":50,"column_start":15,"column_end":30,"is_primary":true,"text":[{"text":" while (true && false) { + --> $DIR/unused_parens_remove_json_suggestion.rs:50:15 | LL | while (true && false) { | ^^^^^^^^^^^^^^^ help: remove these parentheses -" -} +"} +{"message":"aborting due to 9 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 9 previous errors + +"} diff --git a/src/test/ui/object-safety/object-safety-associated-consts.stderr b/src/test/ui/object-safety/object-safety-associated-consts.curr.stderr similarity index 88% rename from src/test/ui/object-safety/object-safety-associated-consts.stderr rename to src/test/ui/object-safety/object-safety-associated-consts.curr.stderr index 7d5aa00356e0..67ef7a62f105 100644 --- a/src/test/ui/object-safety/object-safety-associated-consts.stderr +++ b/src/test/ui/object-safety/object-safety-associated-consts.curr.stderr @@ -1,5 +1,5 @@ error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-associated-consts.rs:9:1 + --> $DIR/object-safety-associated-consts.rs:12:1 | LL | const X: usize; | - the trait cannot contain associated consts like `X` diff --git a/src/test/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr b/src/test/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr new file mode 100644 index 000000000000..20993a680ba4 --- /dev/null +++ b/src/test/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr @@ -0,0 +1,15 @@ +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/object-safety-associated-consts.rs:14:5 + | +LL | const X: usize; + | - the trait cannot contain associated consts like `X` +... +LL | t + | ^ the trait `Bar` cannot be made into an object + | + = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Bar>` for `&T` + = note: required by cast to type `&dyn Bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/object-safety/object-safety-associated-consts.rs b/src/test/ui/object-safety/object-safety-associated-consts.rs index 5900019ea915..e1a772e5ab2f 100644 --- a/src/test/ui/object-safety/object-safety-associated-consts.rs +++ b/src/test/ui/object-safety/object-safety-associated-consts.rs @@ -1,14 +1,18 @@ // Check that we correctly prevent users from making trait objects // from traits with associated consts. +// +// revisions: curr object_safe_for_dispatch +#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] trait Bar { const X: usize; } fn make_bar(t: &T) -> &dyn Bar { - //~^ ERROR E0038 + //[curr]~^ ERROR E0038 t + //[object_safe_for_dispatch]~^ ERROR E0038 } fn main() { diff --git a/src/test/ui/object-safety/object-safety-generics.stderr b/src/test/ui/object-safety/object-safety-generics.curr.stderr similarity index 89% rename from src/test/ui/object-safety/object-safety-generics.stderr rename to src/test/ui/object-safety/object-safety-generics.curr.stderr index b25e0052e416..8ae9236a5c32 100644 --- a/src/test/ui/object-safety/object-safety-generics.stderr +++ b/src/test/ui/object-safety/object-safety-generics.curr.stderr @@ -1,5 +1,5 @@ error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-generics.rs:14:1 + --> $DIR/object-safety-generics.rs:18:1 | LL | fn bar(&self, t: T); | --- method `bar` has generic type parameters @@ -8,7 +8,7 @@ LL | fn make_bar(t: &T) -> &dyn Bar { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-generics.rs:19:1 + --> $DIR/object-safety-generics.rs:24:1 | LL | fn bar(&self, t: T); | --- method `bar` has generic type parameters diff --git a/src/test/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr b/src/test/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr new file mode 100644 index 000000000000..d3d8d3688883 --- /dev/null +++ b/src/test/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr @@ -0,0 +1,27 @@ +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/object-safety-generics.rs:20:5 + | +LL | fn bar(&self, t: T); + | --- method `bar` has generic type parameters +... +LL | t + | ^ the trait `Bar` cannot be made into an object + | + = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Bar>` for `&T` + = note: required by cast to type `&dyn Bar` + +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/object-safety-generics.rs:26:5 + | +LL | fn bar(&self, t: T); + | --- method `bar` has generic type parameters +... +LL | t as &dyn Bar + | ^ the trait `Bar` cannot be made into an object + | + = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Bar>` for `&T` + = note: required by cast to type `&dyn Bar` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/object-safety/object-safety-generics.rs b/src/test/ui/object-safety/object-safety-generics.rs index d63ea28c8f22..63dcd169925e 100644 --- a/src/test/ui/object-safety/object-safety-generics.rs +++ b/src/test/ui/object-safety/object-safety-generics.rs @@ -1,6 +1,10 @@ // Check that we correctly prevent users from making trait objects // from traits with generic methods, unless `where Self : Sized` is // present. +// revisions: curr object_safe_for_dispatch + +#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] + trait Bar { fn bar(&self, t: T); @@ -12,13 +16,15 @@ trait Quux { } fn make_bar(t: &T) -> &dyn Bar { - //~^ ERROR E0038 + //[curr]~^ ERROR E0038 t + //[object_safe_for_dispatch]~^ ERROR E0038 } fn make_bar_explicit(t: &T) -> &dyn Bar { - //~^ ERROR E0038 + //[curr]~^ ERROR E0038 t as &dyn Bar + //[object_safe_for_dispatch]~^ ERROR E0038 } fn make_quux(t: &T) -> &dyn Quux { diff --git a/src/test/ui/object-safety/object-safety-mentions-Self.stderr b/src/test/ui/object-safety/object-safety-mentions-Self.curr.stderr similarity index 83% rename from src/test/ui/object-safety/object-safety-mentions-Self.stderr rename to src/test/ui/object-safety/object-safety-mentions-Self.curr.stderr index 971e79cb0210..297cd876187f 100644 --- a/src/test/ui/object-safety/object-safety-mentions-Self.stderr +++ b/src/test/ui/object-safety/object-safety-mentions-Self.curr.stderr @@ -1,5 +1,5 @@ error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-mentions-Self.rs:17:1 + --> $DIR/object-safety-mentions-Self.rs:22:1 | LL | fn bar(&self, x: &Self); | --- method `bar` references the `Self` type in its parameters or return type @@ -8,10 +8,10 @@ LL | fn make_bar(t: &T) -> &dyn Bar { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object error[E0038]: the trait `Baz` cannot be made into an object - --> $DIR/object-safety-mentions-Self.rs:22:1 + --> $DIR/object-safety-mentions-Self.rs:28:1 | -LL | fn bar(&self) -> Self; - | --- method `bar` references the `Self` type in its parameters or return type +LL | fn baz(&self) -> Self; + | --- method `baz` references the `Self` type in its parameters or return type ... LL | fn make_baz(t: &T) -> &dyn Baz { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Baz` cannot be made into an object diff --git a/src/test/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr b/src/test/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr new file mode 100644 index 000000000000..03b2b8da0753 --- /dev/null +++ b/src/test/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr @@ -0,0 +1,27 @@ +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/object-safety-mentions-Self.rs:24:5 + | +LL | fn bar(&self, x: &Self); + | --- method `bar` references the `Self` type in its parameters or return type +... +LL | t + | ^ the trait `Bar` cannot be made into an object + | + = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Bar>` for `&T` + = note: required by cast to type `&dyn Bar` + +error[E0038]: the trait `Baz` cannot be made into an object + --> $DIR/object-safety-mentions-Self.rs:30:5 + | +LL | fn baz(&self) -> Self; + | --- method `baz` references the `Self` type in its parameters or return type +... +LL | t + | ^ the trait `Baz` cannot be made into an object + | + = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Baz>` for `&T` + = note: required by cast to type `&dyn Baz` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/object-safety/object-safety-mentions-Self.rs b/src/test/ui/object-safety/object-safety-mentions-Self.rs index f13ffe536267..412d16ff3c7c 100644 --- a/src/test/ui/object-safety/object-safety-mentions-Self.rs +++ b/src/test/ui/object-safety/object-safety-mentions-Self.rs @@ -1,27 +1,34 @@ // Check that we correctly prevent users from making trait objects // form traits that make use of `Self` in an argument or return // position, unless `where Self : Sized` is present.. +// +// revisions: curr object_safe_for_dispatch + +#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] + trait Bar { fn bar(&self, x: &Self); } trait Baz { - fn bar(&self) -> Self; + fn baz(&self) -> Self; } trait Quux { - fn get(&self, s: &Self) -> Self where Self : Sized; + fn quux(&self, s: &Self) -> Self where Self : Sized; } fn make_bar(t: &T) -> &dyn Bar { - //~^ ERROR E0038 - loop { } + //[curr]~^ ERROR E0038 + t + //[object_safe_for_dispatch]~^ ERROR E0038 } fn make_baz(t: &T) -> &dyn Baz { - //~^ ERROR E0038 + //[curr]~^ ERROR E0038 t + //[object_safe_for_dispatch]~^ ERROR E0038 } fn make_quux(t: &T) -> &dyn Quux { @@ -32,5 +39,4 @@ fn make_quux_explicit(t: &T) -> &dyn Quux { t as &dyn Quux } -fn main() { -} +fn main() {} diff --git a/src/test/ui/object-safety/object-safety-no-static.curr.stderr b/src/test/ui/object-safety/object-safety-no-static.curr.stderr new file mode 100644 index 000000000000..1641ce577719 --- /dev/null +++ b/src/test/ui/object-safety/object-safety-no-static.curr.stderr @@ -0,0 +1,12 @@ +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/object-safety-no-static.rs:12:1 + | +LL | fn foo() {} + | --- associated function `foo` has no `self` parameter +... +LL | fn diverges() -> Box { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr b/src/test/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr new file mode 100644 index 000000000000..91a9285b63cc --- /dev/null +++ b/src/test/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr @@ -0,0 +1,15 @@ +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/object-safety-no-static.rs:22:27 + | +LL | fn foo() {} + | --- associated function `foo` has no `self` parameter +... +LL | let b: Box = Box::new(Bar); + | ^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object + | + = note: required because of the requirements on the impl of `std::ops::CoerceUnsized>` for `std::boxed::Box` + = note: required by cast to type `std::boxed::Box` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/object-safety/object-safety-no-static.rs b/src/test/ui/object-safety/object-safety-no-static.rs index 55d31ce80876..03b622174838 100644 --- a/src/test/ui/object-safety/object-safety-no-static.rs +++ b/src/test/ui/object-safety/object-safety-no-static.rs @@ -1,14 +1,24 @@ // Check that we correctly prevent users from making trait objects // from traits with static methods. +// +// revisions: curr object_safe_for_dispatch + +#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] trait Foo { - fn foo(); + fn foo() {} } -fn foo_implicit(b: Box) -> Box { - //~^ ERROR E0038 +fn diverges() -> Box { + //[curr]~^ ERROR E0038 loop { } } +struct Bar; + +impl Foo for Bar {} + fn main() { + let b: Box = Box::new(Bar); + //[object_safe_for_dispatch]~^ ERROR E0038 } diff --git a/src/test/ui/object-safety/object-safety-sized-2.stderr b/src/test/ui/object-safety/object-safety-sized-2.curr.stderr similarity index 89% rename from src/test/ui/object-safety/object-safety-sized-2.stderr rename to src/test/ui/object-safety/object-safety-sized-2.curr.stderr index dcaf2ff0bc29..1e1d2bf64c42 100644 --- a/src/test/ui/object-safety/object-safety-sized-2.stderr +++ b/src/test/ui/object-safety/object-safety-sized-2.curr.stderr @@ -1,5 +1,5 @@ error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-sized-2.rs:10:1 + --> $DIR/object-safety-sized-2.rs:14:1 | LL | fn make_bar(t: &T) -> &dyn Bar { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object diff --git a/src/test/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr b/src/test/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr new file mode 100644 index 000000000000..06ecfd019c84 --- /dev/null +++ b/src/test/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr @@ -0,0 +1,13 @@ +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/object-safety-sized-2.rs:16:5 + | +LL | t + | ^ the trait `Bar` cannot be made into an object + | + = note: the trait cannot require that `Self : Sized` + = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Bar>` for `&T` + = note: required by cast to type `&dyn Bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/object-safety/object-safety-sized-2.rs b/src/test/ui/object-safety/object-safety-sized-2.rs index 7235b22404e2..1e79b8cd917c 100644 --- a/src/test/ui/object-safety/object-safety-sized-2.rs +++ b/src/test/ui/object-safety/object-safety-sized-2.rs @@ -1,5 +1,9 @@ // Check that we correctly prevent users from making trait objects // from traits where `Self : Sized`. +// +// revisions: curr object_safe_for_dispatch + +#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] trait Bar where Self : Sized @@ -8,8 +12,9 @@ trait Bar } fn make_bar(t: &T) -> &dyn Bar { - //~^ ERROR E0038 - loop { } + //[curr]~^ ERROR E0038 + t + //[object_safe_for_dispatch]~^ ERROR E0038 } fn main() { diff --git a/src/test/ui/object-safety/object-safety-sized.stderr b/src/test/ui/object-safety/object-safety-sized.curr.stderr similarity index 90% rename from src/test/ui/object-safety/object-safety-sized.stderr rename to src/test/ui/object-safety/object-safety-sized.curr.stderr index 98bc73e38d4c..1a67e79e83d3 100644 --- a/src/test/ui/object-safety/object-safety-sized.stderr +++ b/src/test/ui/object-safety/object-safety-sized.curr.stderr @@ -1,5 +1,5 @@ error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/object-safety-sized.rs:8:1 + --> $DIR/object-safety-sized.rs:12:1 | LL | fn make_bar(t: &T) -> &dyn Bar { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object diff --git a/src/test/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr b/src/test/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr new file mode 100644 index 000000000000..3d88dfc40ed3 --- /dev/null +++ b/src/test/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr @@ -0,0 +1,13 @@ +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/object-safety-sized.rs:14:5 + | +LL | t + | ^ the trait `Bar` cannot be made into an object + | + = note: the trait cannot require that `Self : Sized` + = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Bar>` for `&T` + = note: required by cast to type `&dyn Bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/object-safety/object-safety-sized.rs b/src/test/ui/object-safety/object-safety-sized.rs index 1312bb34717e..b424b892d3b4 100644 --- a/src/test/ui/object-safety/object-safety-sized.rs +++ b/src/test/ui/object-safety/object-safety-sized.rs @@ -1,13 +1,18 @@ // Check that we correctly prevent users from making trait objects // from traits where `Self : Sized`. +// +// revisions: curr object_safe_for_dispatch + +#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] trait Bar : Sized { fn bar(&self, t: T); } fn make_bar(t: &T) -> &dyn Bar { - //~^ ERROR E0038 + //[curr]~^ ERROR E0038 t + //[object_safe_for_dispatch]~^ ERROR E0038 } fn main() { diff --git a/src/test/ui/repr/repr-packed-contains-align.stderr b/src/test/ui/repr/repr-packed-contains-align.stderr index 219516d8abc4..df001d6b5f2a 100644 --- a/src/test/ui/repr/repr-packed-contains-align.stderr +++ b/src/test/ui/repr/repr-packed-contains-align.stderr @@ -56,3 +56,4 @@ LL | | } error: aborting due to 8 previous errors +For more information about this error, try `rustc --explain E0588`. diff --git a/src/test/ui/rfc-2027-object-safe-for-dispatch/downcast-unsafe-trait-objects.rs b/src/test/ui/rfc-2027-object-safe-for-dispatch/downcast-unsafe-trait-objects.rs new file mode 100644 index 000000000000..fa04f4b12d5f --- /dev/null +++ b/src/test/ui/rfc-2027-object-safe-for-dispatch/downcast-unsafe-trait-objects.rs @@ -0,0 +1,23 @@ +// Check that we if we get ahold of an object unsafe trait +// object with auto traits and lifetimes, we can downcast it +// +// check-pass + +#![feature(object_safe_for_dispatch)] + +trait Trait: Sized {} + +fn downcast_auto(t: &(dyn Trait + Send)) -> &dyn Trait { + t +} + +fn downcast_lifetime<'a, 'b, 't>(t: &'a (dyn Trait + 't)) + -> &'b (dyn Trait + 't) +where + 'a: 'b, + 't: 'a + 'b, +{ + t +} + +fn main() {} diff --git a/src/test/ui/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs b/src/test/ui/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs new file mode 100644 index 000000000000..1dea40122656 --- /dev/null +++ b/src/test/ui/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs @@ -0,0 +1,69 @@ +// Check that we can manually implement an object +// unsafe trait for its trait object +// +// run-pass + +#![feature(object_safe_for_dispatch)] + +trait Bad { + fn stat() -> char { + 'A' + } + fn virt(&self) -> char { + 'B' + } + fn indirect(&self) -> char { + Self::stat() + } +} + +trait Good { + fn good_virt(&self) -> char { + panic!() + } + fn good_indirect(&self) -> char { + panic!() + } +} + +impl<'a> Bad for dyn Bad + 'a { + fn stat() -> char { + 'C' + } + fn virt(&self) -> char { + 'D' + } +} + +struct Struct {} + +impl Bad for Struct {} + +impl Good for Struct {} + +fn main() { + let s = Struct {}; + + let mut res = String::new(); + + // Directly call static + res.push(Struct::stat()); // "A" + res.push(::stat()); // "AC" + + let good: &dyn Good = &s; + + // These look similar enough... + let bad = unsafe { std::mem::transmute::<&dyn Good, &dyn Bad>(good) }; + + // Call virtual + res.push(s.virt()); // "ACB" + res.push(bad.virt()); // "ACBD" + + // Indirectly call static + res.push(s.indirect()); // "ACBDA" + res.push(bad.indirect()); // "ACBDAC" + + if &res != "ACBDAC" { + panic!(); + } +} diff --git a/src/test/ui/rfc-2027-object-safe-for-dispatch/static-dispatch-unsafe-object.rs b/src/test/ui/rfc-2027-object-safe-for-dispatch/static-dispatch-unsafe-object.rs new file mode 100644 index 000000000000..df97d2c13278 --- /dev/null +++ b/src/test/ui/rfc-2027-object-safe-for-dispatch/static-dispatch-unsafe-object.rs @@ -0,0 +1,37 @@ +// Check that we can statically dispatch methods for object +// unsafe trait objects, directly and indirectly +// +// check-pass + +#![feature(object_safe_for_dispatch)] + +trait Statics { + fn plain() {} + fn generic() {} +} + +trait Trait: Sized {} + +impl<'a> Statics for dyn Trait + 'a {} + +fn static_poly() { + T::plain(); + T::generic::(); +} + +fn inferred_poly(t: &T) { + static_poly::(); + T::plain(); + T::generic::(); +} + +fn call(t: &dyn Trait) { + static_poly::(); + inferred_poly(t); +} + +fn main() { + static_poly::(); + ::plain(); + ::generic::() +} diff --git a/src/test/ui/self/arbitrary-self-types-not-object-safe.curr.stderr b/src/test/ui/self/arbitrary-self-types-not-object-safe.curr.stderr new file mode 100644 index 000000000000..cdffc1d86edf --- /dev/null +++ b/src/test/ui/self/arbitrary-self-types-not-object-safe.curr.stderr @@ -0,0 +1,24 @@ +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/arbitrary-self-types-not-object-safe.rs:34:32 + | +LL | fn foo(self: &Rc) -> usize; + | --- method `foo`'s `self` parameter cannot be dispatched on +... +LL | let x = Rc::new(5usize) as Rc; + | ^^^^^^^^^^^ the trait `Foo` cannot be made into an object + +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/arbitrary-self-types-not-object-safe.rs:34:13 + | +LL | fn foo(self: &Rc) -> usize; + | --- method `foo`'s `self` parameter cannot be dispatched on +... +LL | let x = Rc::new(5usize) as Rc; + | ^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object + | + = note: required because of the requirements on the impl of `std::ops::CoerceUnsized>` for `std::rc::Rc` + = note: required by cast to type `std::rc::Rc` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr b/src/test/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr new file mode 100644 index 000000000000..725632a12126 --- /dev/null +++ b/src/test/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr @@ -0,0 +1,15 @@ +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/arbitrary-self-types-not-object-safe.rs:34:13 + | +LL | fn foo(self: &Rc) -> usize; + | --- method `foo`'s `self` parameter cannot be dispatched on +... +LL | let x = Rc::new(5usize) as Rc; + | ^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object + | + = note: required because of the requirements on the impl of `std::ops::CoerceUnsized>` for `std::rc::Rc` + = note: required by cast to type `std::rc::Rc` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/self/arbitrary-self-types-not-object-safe.rs b/src/test/ui/self/arbitrary-self-types-not-object-safe.rs index 7443d888c9ec..2eeabad28db0 100644 --- a/src/test/ui/self/arbitrary-self-types-not-object-safe.rs +++ b/src/test/ui/self/arbitrary-self-types-not-object-safe.rs @@ -1,3 +1,6 @@ +// revisions: curr object_safe_for_dispatch + +#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))] #![feature(arbitrary_self_types)] use std::rc::Rc; @@ -29,8 +32,9 @@ impl Bar for usize { fn make_foo() { let x = Rc::new(5usize) as Rc; - //~^ ERROR E0038 - //~| ERROR E0038 + //[curr]~^ ERROR E0038 + //[curr]~| ERROR E0038 + //[object_safe_for_dispatch]~^^^ ERROR E0038 } fn make_bar() { diff --git a/src/test/ui/signal-alternate-stack-cleanup.rs b/src/test/ui/signal-alternate-stack-cleanup.rs index 787ff51799a8..8fef66eac8de 100644 --- a/src/test/ui/signal-alternate-stack-cleanup.rs +++ b/src/test/ui/signal-alternate-stack-cleanup.rs @@ -7,6 +7,7 @@ // ignore-wasm32-bare no libc // ignore-windows // ignore-sgx no libc +// ignore-vxworks no SIGWINCH in user space #![feature(rustc_private)] extern crate libc; diff --git a/src/test/ui/structs-enums/rec-align-u64.rs b/src/test/ui/structs-enums/rec-align-u64.rs index c4e9e9ea5ee1..680a690ba34e 100644 --- a/src/test/ui/structs-enums/rec-align-u64.rs +++ b/src/test/ui/structs-enums/rec-align-u64.rs @@ -40,7 +40,8 @@ struct Outer { target_os = "macos", target_os = "netbsd", target_os = "openbsd", - target_os = "solaris"))] + target_os = "solaris", + target_os = "vxworks"))] mod m { #[cfg(target_arch = "x86")] pub mod m { diff --git a/src/test/ui/traits/trait-object-safety.stderr b/src/test/ui/traits/trait-object-safety.stderr index 3ac1e96b30c9..028e9eedd641 100644 --- a/src/test/ui/traits/trait-object-safety.stderr +++ b/src/test/ui/traits/trait-object-safety.stderr @@ -8,6 +8,7 @@ LL | let _: &dyn Tr = &St; | ^^^ the trait `Tr` cannot be made into an object | = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Tr>` for `&St` + = note: required by cast to type `&dyn Tr` error[E0038]: the trait `Tr` cannot be made into an object --> $DIR/trait-object-safety.rs:15:12 diff --git a/src/test/ui/traits/trait-test-2.stderr b/src/test/ui/traits/trait-test-2.stderr index 83c2c0652749..9b750d382ec9 100644 --- a/src/test/ui/traits/trait-test-2.stderr +++ b/src/test/ui/traits/trait-test-2.stderr @@ -33,6 +33,7 @@ LL | (box 10 as Box).dup(); | ^^^^^^ the trait `bar` cannot be made into an object | = note: required because of the requirements on the impl of `std::ops::CoerceUnsized>` for `std::boxed::Box<{integer}>` + = note: required by cast to type `std::boxed::Box` error: aborting due to 4 previous errors diff --git a/src/test/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs b/src/test/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs new file mode 100644 index 000000000000..12eb75ae4c01 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs @@ -0,0 +1,17 @@ +// check-pass + +#![feature(type_alias_impl_trait)] + +type T = impl Sized; +// The concrete type referred by impl-trait-type-alias(`T`) is guaranteed +// to be the same as where it occurs, whereas `impl Trait`'s instance is location sensitive; +// so difference assertion should not be declared on impl-trait-type-alias's instances. +// for details, check RFC-2515: +// https://github.com/rust-lang/rfcs/blob/master/text/2515-type_alias_impl_trait.md + +fn take(_: fn() -> T) {} + +fn main() { + take(|| {}); + take(|| {}); +} diff --git a/src/test/ui/wf/wf-convert-unsafe-trait-obj-box.rs b/src/test/ui/wf/wf-convert-unsafe-trait-obj-box.rs new file mode 100644 index 000000000000..ffdb49a3be5c --- /dev/null +++ b/src/test/ui/wf/wf-convert-unsafe-trait-obj-box.rs @@ -0,0 +1,18 @@ +// Check that we do not allow casts or coercions +// to object unsafe trait objects inside a Box + +#![feature(object_safe_for_dispatch)] + +trait Trait: Sized {} + +struct S; + +impl Trait for S {} + +fn takes_box(t: Box) {} + +fn main() { + Box::new(S) as Box; //~ ERROR E0038 + let t_box: Box = Box::new(S); //~ ERROR E0038 + takes_box(Box::new(S)); //~ ERROR E0038 +} diff --git a/src/test/ui/wf/wf-convert-unsafe-trait-obj-box.stderr b/src/test/ui/wf/wf-convert-unsafe-trait-obj-box.stderr new file mode 100644 index 000000000000..0b63aef2bce1 --- /dev/null +++ b/src/test/ui/wf/wf-convert-unsafe-trait-obj-box.stderr @@ -0,0 +1,33 @@ +error[E0038]: the trait `Trait` cannot be made into an object + --> $DIR/wf-convert-unsafe-trait-obj-box.rs:16:33 + | +LL | let t_box: Box = Box::new(S); + | ^^^^^^^^^^^ the trait `Trait` cannot be made into an object + | + = note: the trait cannot require that `Self : Sized` + = note: required because of the requirements on the impl of `std::ops::CoerceUnsized>` for `std::boxed::Box` + = note: required by cast to type `std::boxed::Box` + +error[E0038]: the trait `Trait` cannot be made into an object + --> $DIR/wf-convert-unsafe-trait-obj-box.rs:17:15 + | +LL | takes_box(Box::new(S)); + | ^^^^^^^^^^^ the trait `Trait` cannot be made into an object + | + = note: the trait cannot require that `Self : Sized` + = note: required because of the requirements on the impl of `std::ops::CoerceUnsized>` for `std::boxed::Box` + = note: required by cast to type `std::boxed::Box<(dyn Trait + 'static)>` + +error[E0038]: the trait `Trait` cannot be made into an object + --> $DIR/wf-convert-unsafe-trait-obj-box.rs:15:5 + | +LL | Box::new(S) as Box; + | ^^^^^^^^^^^ the trait `Trait` cannot be made into an object + | + = note: the trait cannot require that `Self : Sized` + = note: required because of the requirements on the impl of `std::ops::CoerceUnsized>` for `std::boxed::Box` + = note: required by cast to type `std::boxed::Box` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/wf/wf-convert-unsafe-trait-obj.rs b/src/test/ui/wf/wf-convert-unsafe-trait-obj.rs new file mode 100644 index 000000000000..143b854ed6b2 --- /dev/null +++ b/src/test/ui/wf/wf-convert-unsafe-trait-obj.rs @@ -0,0 +1,18 @@ +// Check that we do not allow casts or coercions +// to object unsafe trait objects by ref + +#![feature(object_safe_for_dispatch)] + +trait Trait: Sized {} + +struct S; + +impl Trait for S {} + +fn takes_trait(t: &dyn Trait) {} + +fn main() { + &S as &dyn Trait; //~ ERROR E0038 + let t: &dyn Trait = &S; //~ ERROR E0038 + takes_trait(&S); //~ ERROR E0038 +} diff --git a/src/test/ui/wf/wf-convert-unsafe-trait-obj.stderr b/src/test/ui/wf/wf-convert-unsafe-trait-obj.stderr new file mode 100644 index 000000000000..7aeefd731fb2 --- /dev/null +++ b/src/test/ui/wf/wf-convert-unsafe-trait-obj.stderr @@ -0,0 +1,33 @@ +error[E0038]: the trait `Trait` cannot be made into an object + --> $DIR/wf-convert-unsafe-trait-obj.rs:16:25 + | +LL | let t: &dyn Trait = &S; + | ^^ the trait `Trait` cannot be made into an object + | + = note: the trait cannot require that `Self : Sized` + = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Trait>` for `&S` + = note: required by cast to type `&dyn Trait` + +error[E0038]: the trait `Trait` cannot be made into an object + --> $DIR/wf-convert-unsafe-trait-obj.rs:17:17 + | +LL | takes_trait(&S); + | ^^ the trait `Trait` cannot be made into an object + | + = note: the trait cannot require that `Self : Sized` + = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Trait>` for `&S` + = note: required by cast to type `&dyn Trait` + +error[E0038]: the trait `Trait` cannot be made into an object + --> $DIR/wf-convert-unsafe-trait-obj.rs:15:5 + | +LL | &S as &dyn Trait; + | ^^ the trait `Trait` cannot be made into an object + | + = note: the trait cannot require that `Self : Sized` + = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Trait>` for `&S` + = note: required by cast to type `&dyn Trait` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/wf/wf-unsafe-trait-obj-match.rs b/src/test/ui/wf/wf-unsafe-trait-obj-match.rs new file mode 100644 index 000000000000..c8731a8ecafa --- /dev/null +++ b/src/test/ui/wf/wf-unsafe-trait-obj-match.rs @@ -0,0 +1,29 @@ +// Check that we do not allow coercions to object +// unsafe trait objects in match arms + +#![feature(object_safe_for_dispatch)] + +trait Trait: Sized {} + +struct S; + +impl Trait for S {} + +struct R; + +impl Trait for R {} + +fn opt() -> Option<()> { + Some(()) +} + +fn main() { + match opt() { + Some(()) => &S, + None => &R, //~ ERROR E0308 + } + let t: &dyn Trait = match opt() { //~ ERROR E0038 + Some(()) => &S, //~ ERROR E0038 + None => &R, + }; +} diff --git a/src/test/ui/wf/wf-unsafe-trait-obj-match.stderr b/src/test/ui/wf/wf-unsafe-trait-obj-match.stderr new file mode 100644 index 000000000000..185b1e6c36b5 --- /dev/null +++ b/src/test/ui/wf/wf-unsafe-trait-obj-match.stderr @@ -0,0 +1,38 @@ +error[E0308]: match arms have incompatible types + --> $DIR/wf-unsafe-trait-obj-match.rs:23:17 + | +LL | / match opt() { +LL | | Some(()) => &S, + | | -- this is found to be of type `&S` +LL | | None => &R, + | | ^^ expected struct `S`, found struct `R` +LL | | } + | |_____- `match` arms have incompatible types + | + = note: expected type `&S` + found type `&R` + +error[E0038]: the trait `Trait` cannot be made into an object + --> $DIR/wf-unsafe-trait-obj-match.rs:26:21 + | +LL | Some(()) => &S, + | ^^ the trait `Trait` cannot be made into an object + | + = note: the trait cannot require that `Self : Sized` + = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Trait>` for `&S` + = note: required by cast to type `&dyn Trait` + +error[E0038]: the trait `Trait` cannot be made into an object + --> $DIR/wf-unsafe-trait-obj-match.rs:25:25 + | +LL | let t: &dyn Trait = match opt() { + | ^^^^^^^^^^^ the trait `Trait` cannot be made into an object + | + = note: the trait cannot require that `Self : Sized` + = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Trait>` for `&R` + = note: required by cast to type `&dyn Trait` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0038, E0308. +For more information about an error, try `rustc --explain E0038`. diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index bc6c19738709..2a189a92f4b1 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -401,6 +401,7 @@ impl Builder { fn add_packages_to(&mut self, manifest: &mut Manifest) { let mut package = |name, targets| self.package(name, &mut manifest.pkg, targets); package("rustc", HOSTS); + package("rustc-dev", HOSTS); package("cargo", HOSTS); package("rust-mingw", MINGW); package("rust-std", TARGETS); @@ -428,6 +429,13 @@ impl Builder { "rls-preview", "rust-src", "llvm-tools-preview", "lldb-preview", "rust-analysis", "miri-preview" ]); + + // The compiler libraries are not stable for end users, but `rustc-dev` was only recently + // split out of `rust-std`. We'll include it by default as a transition for nightly users. + if self.rust_release == "nightly" { + self.extend_profile("default", &mut manifest.profiles, &["rustc-dev"]); + self.extend_profile("complete", &mut manifest.profiles, &["rustc-dev"]); + } } fn add_renames_to(&self, manifest: &mut Manifest) { @@ -483,6 +491,15 @@ impl Builder { components.push(host_component("rust-mingw")); } + // The compiler libraries are not stable for end users, but `rustc-dev` was only recently + // split out of `rust-std`. We'll include it by default as a transition for nightly users, + // but ship it as an optional component on the beta and stable channels. + if self.rust_release == "nightly" { + components.push(host_component("rustc-dev")); + } else { + extensions.push(host_component("rustc-dev")); + } + // Tools are always present in the manifest, // but might be marked as unavailable if they weren't built. extensions.extend(vec![ @@ -500,6 +517,11 @@ impl Builder { .filter(|&&target| target != host) .map(|target| Component::from_str("rust-std", target)) ); + extensions.extend( + HOSTS.iter() + .filter(|&&target| target != host) + .map(|target| Component::from_str("rustc-dev", target)) + ); extensions.push(Component::from_str("rust-src", "*")); // If the components/extensions don't actually exist for this @@ -536,6 +558,14 @@ impl Builder { dst.insert(profile_name.to_owned(), pkgs.iter().map(|s| (*s).to_owned()).collect()); } + fn extend_profile(&mut self, + profile_name: &str, + dst: &mut BTreeMap>, + pkgs: &[&str]) { + dst.get_mut(profile_name).expect("existing profile") + .extend(pkgs.iter().map(|s| (*s).to_owned())); + } + fn package(&mut self, pkgname: &str, dst: &mut BTreeMap, diff --git a/src/tools/cargo b/src/tools/cargo index 3a9abe3f0655..3ba5f27170db 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 3a9abe3f065554a7fbc59f440df2baba4a6e47ee +Subproject commit 3ba5f27170db10af7a92f2b682e049397197b8fa diff --git a/src/tools/clippy b/src/tools/clippy index cbedd97b3a58..e8d5a9e95c14 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit cbedd97b3a58023eff365a2fa74700d06115144a +Subproject commit e8d5a9e95c145a3a9be89c582d8a6f88d4ea7037 diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs index e8a7252cb767..79c98b780eb6 100644 --- a/src/tools/linkchecker/main.rs +++ b/src/tools/linkchecker/main.rs @@ -126,7 +126,6 @@ fn check(cache: &mut Cache, // FIXME(#32129) if file.ends_with("std/string/struct.String.html") || file.ends_with("interpret/struct.ImmTy.html") || - file.ends_with("symbol/struct.InternedString.html") || file.ends_with("ast/struct.ThinVec.html") || file.ends_with("util/struct.ThinVec.html") || file.ends_with("layout/struct.TyLayout.html") ||