diff options
| author | Baoshan <pangbw@gmail.com> | 2019-08-29 09:29:23 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-08-29 09:29:23 -0700 |
| commit | 043c19c69c0beac3696cb82d44476ba4298a6b07 (patch) | |
| tree | 1813e5dd1e4efd5806f401968b4ed34b8c9c76ac /src | |
| parent | cae6d66d9989857e321e0963142b08b1517dc723 (diff) | |
| parent | 76f17219c71973fd4a58f2f8020eec4d8f5dcd11 (diff) | |
| download | rust-043c19c69c0beac3696cb82d44476ba4298a6b07.tar.gz rust-043c19c69c0beac3696cb82d44476ba4298a6b07.zip | |
Merge branch 'master' into bpang-runtest
Diffstat (limited to 'src')
788 files changed, 10660 insertions, 5803 deletions
diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index 54b689fb062..ce92ce02696 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -37,7 +37,7 @@ fn main() { let mut new = None; if let Some(current_as_str) = args[i].to_str() { if (&*args[i - 1] == "-C" && current_as_str.starts_with("metadata")) || - current_as_str.starts_with("-Cmetadata") { + current_as_str.starts_with("-Cmetadata") { new = Some(format!("{}-{}", current_as_str, s)); } } @@ -45,18 +45,6 @@ fn main() { } } - // Drop `--error-format json` because despite our desire for json messages - // from Cargo we don't want any from rustc itself. - if let Some(n) = args.iter().position(|n| n == "--error-format") { - args.remove(n); - args.remove(n); - } - - if let Some(s) = env::var_os("RUSTC_ERROR_FORMAT") { - args.push("--error-format".into()); - args.push(s); - } - // Detect whether or not we're a build script depending on whether --target // is passed (a bit janky...) let target = args.windows(2) @@ -101,7 +89,7 @@ fn main() { if let Some(crate_name) = crate_name { if let Some(target) = env::var_os("RUSTC_TIME") { if target == "all" || - target.into_string().unwrap().split(",").any(|c| c.trim() == crate_name) + target.into_string().unwrap().split(",").any(|c| c.trim() == crate_name) { cmd.arg("-Ztime"); } @@ -110,8 +98,17 @@ fn main() { // Non-zero stages must all be treated uniformly to avoid problems when attempting to uplift // compiler libraries and such from stage 1 to 2. + // + // FIXME: the fact that core here is excluded is due to core_arch from our stdarch submodule + // being broken on the beta compiler with bootstrap passed, so this is a temporary workaround + // (we've just snapped, so there are no cfg(bootstrap) related annotations in core). if stage == "0" { - cmd.arg("--cfg").arg("bootstrap"); + if crate_name != Some("core") { + cmd.arg("--cfg").arg("bootstrap"); + } else { + // NOTE(eddyb) see FIXME above, except now we need annotations again in core. + cmd.arg("--cfg").arg("boostrap_stdarch_ignore_this"); + } } // Print backtrace in case of ICE @@ -132,10 +129,7 @@ fn main() { cmd.arg("-Dwarnings"); cmd.arg("-Drust_2018_idioms"); cmd.arg("-Dunused_lifetimes"); - // cfg(not(bootstrap)): Remove this during the next stage 0 compiler update. - // `-Drustc::internal` is a new feature and `rustc_version` mis-reports the `stage`. - let cfg_not_bootstrap = stage != "0" && crate_name != Some("rustc_version"); - if cfg_not_bootstrap && use_internal_lints(crate_name) { + if use_internal_lints(crate_name) { cmd.arg("-Zunstable-options"); cmd.arg("-Drustc::internal"); } @@ -287,10 +281,6 @@ fn main() { cmd.arg("-C").arg("target-feature=-crt-static"); } } - - if let Ok(map) = env::var("RUSTC_DEBUGINFO_MAP") { - cmd.arg("--remap-path-prefix").arg(&map); - } } else { // Override linker if necessary. if let Ok(host_linker) = env::var("RUSTC_HOST_LINKER") { @@ -307,6 +297,10 @@ fn main() { } } + if let Ok(map) = env::var("RUSTC_DEBUGINFO_MAP") { + cmd.arg("--remap-path-prefix").arg(&map); + } + // Force all crates compiled by this compiler to (a) be unstable and (b) // allow the `rustc_private` feature to link to other unstable crates // also in the sysroot. We also do this for host crates, since those diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index e54c9360bae..955809e8074 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -145,7 +145,7 @@ impl StepDescription { only_hosts: S::ONLY_HOSTS, should_run: S::should_run, make_run: S::make_run, - name: unsafe { ::std::intrinsics::type_name::<S>() }, + name: std::any::type_name::<S>(), } } @@ -618,13 +618,7 @@ impl<'a> Builder<'a> { } fn run(self, builder: &Builder<'_>) -> Interned<PathBuf> { - let compiler = self.compiler; - let config = &builder.build.config; - let lib = if compiler.stage >= 1 && config.libdir_relative().is_some() { - builder.build.config.libdir_relative().unwrap() - } else { - Path::new("lib") - }; + let lib = builder.sysroot_libdir_relative(self.compiler); let sysroot = builder .sysroot(self.compiler) .join(lib) @@ -678,6 +672,18 @@ impl<'a> Builder<'a> { } } + /// Returns the compiler's relative libdir where the standard library and other artifacts are + /// found for a compiler's sysroot. + /// + /// For example this returns `lib` on Unix and Windows. + pub fn sysroot_libdir_relative(&self, compiler: Compiler) -> &Path { + match self.config.libdir_relative() { + Some(relative_libdir) if compiler.stage >= 1 + => relative_libdir, + _ => Path::new("lib") + } + } + /// Adds the compiler's directory of dynamic libraries to `cmd`'s dynamic /// library lookup path. pub fn add_rustc_lib_path(&self, compiler: Compiler, cmd: &mut Command) { @@ -754,76 +760,20 @@ impl<'a> Builder<'a> { let mut cargo = Command::new(&self.initial_cargo); let out_dir = self.stage_out(compiler, mode); - // command specific path, we call clear_if_dirty with this - let mut my_out = match cmd { - "build" => self.cargo_out(compiler, mode, target), - - // This is the intended out directory for crate documentation. - "doc" | "rustdoc" => self.crate_doc_out(target), - - _ => self.stage_out(compiler, mode), - }; - - // This is for the original compiler, but if we're forced to use stage 1, then - // std/test/rustc stamps won't exist in stage 2, so we need to get those from stage 1, since - // we copy the libs forward. - let cmp = self.compiler_for(compiler.stage, compiler.host, target); - - let libstd_stamp = match cmd { - "check" | "clippy" | "fix" => check::libstd_stamp(self, cmp, target), - _ => compile::libstd_stamp(self, cmp, target), - }; - - let libtest_stamp = match cmd { - "check" | "clippy" | "fix" => check::libtest_stamp(self, cmp, target), - _ => compile::libtest_stamp(self, cmp, target), - }; - - let librustc_stamp = match cmd { - "check" | "clippy" | "fix" => check::librustc_stamp(self, cmp, target), - _ => compile::librustc_stamp(self, cmp, target), - }; + // Codegen backends are not yet tracked by -Zbinary-dep-depinfo, + // so we need to explicitly clear out if they've been updated. + for backend in self.codegen_backends(compiler) { + self.clear_if_dirty(&out_dir, &backend); + } if cmd == "doc" || cmd == "rustdoc" { - if mode == Mode::Rustc || mode == Mode::ToolRustc || mode == Mode::Codegen { + let my_out = match mode { // This is the intended out directory for compiler documentation. - my_out = self.compiler_doc_out(target); - } + Mode::Rustc | Mode::ToolRustc | Mode::Codegen => self.compiler_doc_out(target), + _ => self.crate_doc_out(target), + }; let rustdoc = self.rustdoc(compiler); self.clear_if_dirty(&my_out, &rustdoc); - } else if cmd != "test" { - match mode { - Mode::Std => { - self.clear_if_dirty(&my_out, &self.rustc(compiler)); - for backend in self.codegen_backends(compiler) { - self.clear_if_dirty(&my_out, &backend); - } - }, - Mode::Test => { - self.clear_if_dirty(&my_out, &libstd_stamp); - }, - Mode::Rustc => { - self.clear_if_dirty(&my_out, &self.rustc(compiler)); - self.clear_if_dirty(&my_out, &libstd_stamp); - self.clear_if_dirty(&my_out, &libtest_stamp); - }, - Mode::Codegen => { - self.clear_if_dirty(&my_out, &librustc_stamp); - }, - Mode::ToolBootstrap => { }, - Mode::ToolStd => { - self.clear_if_dirty(&my_out, &libstd_stamp); - }, - Mode::ToolTest => { - self.clear_if_dirty(&my_out, &libstd_stamp); - self.clear_if_dirty(&my_out, &libtest_stamp); - }, - Mode::ToolRustc => { - self.clear_if_dirty(&my_out, &libstd_stamp); - self.clear_if_dirty(&my_out, &libtest_stamp); - self.clear_if_dirty(&my_out, &librustc_stamp); - }, - } } cargo @@ -861,6 +811,19 @@ impl<'a> Builder<'a> { }, } + // This tells Cargo (and in turn, rustc) to output more complete + // dependency information. Most importantly for rustbuild, this + // includes sysroot artifacts, like libstd, which means that we don't + // need to track those in rustbuild (an error prone process!). This + // feature is currently unstable as there may be some bugs and such, but + // it represents a big improvement in rustbuild's reliability on + // rebuilds, so we're using it here. + // + // For some additional context, see #63470 (the PR originally adding + // this), as well as #63012 which is the tracking issue for this + // feature on the rustc side. + cargo.arg("-Zbinary-dep-depinfo"); + cargo.arg("-j").arg(self.jobs().to_string()); // Remove make-related flags to ensure Cargo can correctly set things up cargo.env_remove("MAKEFLAGS"); @@ -902,12 +865,12 @@ impl<'a> Builder<'a> { stage = compiler.stage; } - let mut extra_args = env::var(&format!("RUSTFLAGS_STAGE_{}", stage)).unwrap_or_default(); + let mut extra_args = String::new(); if stage != 0 { - let s = env::var("RUSTFLAGS_STAGE_NOT_0").unwrap_or_default(); - if !extra_args.is_empty() { - extra_args.push_str(" "); - } + let s = env::var("RUSTFLAGS_NOT_BOOTSTRAP").unwrap_or_default(); + extra_args.push_str(&s); + } else { + let s = env::var("RUSTFLAGS_BOOTSTRAP").unwrap_or_default(); extra_args.push_str(&s); } @@ -980,9 +943,6 @@ impl<'a> Builder<'a> { if let Some(target_linker) = self.linker(target) { cargo.env("RUSTC_TARGET_LINKER", target_linker); } - if let Some(ref error_format) = self.config.rustc_error_format { - cargo.env("RUSTC_ERROR_FORMAT", error_format); - } if !(["build", "check", "clippy", "fix", "rustc"].contains(&cmd)) && want_rustdoc { cargo.env("RUSTDOC_LIBDIR", self.rustc_libdir(compiler)); } diff --git a/src/bootstrap/channel.rs b/src/bootstrap/channel.rs index 8e8d8f5e787..caa4843da4d 100644 --- a/src/bootstrap/channel.rs +++ b/src/bootstrap/channel.rs @@ -13,7 +13,7 @@ use build_helper::output; use crate::Build; // The version number -pub const CFG_RELEASE_NUM: &str = "1.38.0"; +pub const CFG_RELEASE_NUM: &str = "1.39.0"; pub struct GitInfo { inner: Option<Info>, diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 11b082ac3f6..6e6fea6b831 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -245,7 +245,6 @@ impl Step for Rustdoc { let libdir = builder.sysroot_libdir(compiler, target); let hostdir = builder.sysroot_libdir(compiler, compiler.host); add_to_sysroot(&builder, &libdir, &hostdir, &rustdoc_stamp(builder, compiler, target)); - builder.cargo(compiler, Mode::ToolRustc, target, "clean"); } } diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 4cd793adaf5..96987d08159 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -15,7 +15,7 @@ use std::path::{Path, PathBuf}; use std::process::{Command, Stdio, exit}; use std::str; -use build_helper::{output, mtime, t, up_to_date}; +use build_helper::{output, t, up_to_date}; use filetime::FileTime; use serde::Deserialize; use serde_json; @@ -274,8 +274,6 @@ impl Step for StdLink { // for reason why the sanitizers are not built in stage0. copy_apple_sanitizer_dylibs(builder, &builder.native_dir(target), "osx", &libdir); } - - builder.cargo(target_compiler, Mode::ToolStd, target, "clean"); } } @@ -480,8 +478,6 @@ impl Step for TestLink { &builder.sysroot_libdir(target_compiler, compiler.host), &libtest_stamp(builder, compiler, target) ); - - builder.cargo(target_compiler, Mode::ToolTest, target, "clean"); } } @@ -639,7 +635,6 @@ impl Step for RustcLink { &builder.sysroot_libdir(target_compiler, compiler.host), &librustc_stamp(builder, compiler, target) ); - builder.cargo(target_compiler, Mode::ToolRustc, target, "clean"); } } @@ -795,6 +790,9 @@ pub fn build_codegen_backend(builder: &Builder<'_>, if builder.config.llvm_use_libcxx { cargo.env("LLVM_USE_LIBCXX", "1"); } + if builder.config.llvm_optimize && !builder.config.llvm_release_debuginfo { + cargo.env("LLVM_NDEBUG", "1"); + } } _ => panic!("unknown backend: {}", backend), } @@ -1116,10 +1114,6 @@ pub fn run_cargo(builder: &Builder<'_>, }, .. } => (filenames, crate_types), - CargoMessage::CompilerMessage { message } => { - eprintln!("{}", message.rendered); - return; - } _ => return, }; for filename in filenames { @@ -1206,41 +1200,13 @@ pub fn run_cargo(builder: &Builder<'_>, deps.push((path_to_add.into(), false)); } - // Now we want to update the contents of the stamp file, if necessary. First - // we read off the previous contents along with its mtime. If our new - // contents (the list of files to copy) is different or if any dep's mtime - // is newer then we rewrite the stamp file. deps.sort(); - let stamp_contents = fs::read(stamp); - let stamp_mtime = mtime(&stamp); let mut new_contents = Vec::new(); - let mut max = None; - let mut max_path = None; for (dep, proc_macro) in deps.iter() { - let mtime = mtime(dep); - if Some(mtime) > max { - max = Some(mtime); - max_path = Some(dep.clone()); - } new_contents.extend(if *proc_macro { b"h" } else { b"t" }); new_contents.extend(dep.to_str().unwrap().as_bytes()); new_contents.extend(b"\0"); } - let max = max.unwrap(); - let max_path = max_path.unwrap(); - let contents_equal = stamp_contents - .map(|contents| contents == new_contents) - .unwrap_or_default(); - if contents_equal && max <= stamp_mtime { - builder.verbose(&format!("not updating {:?}; contents equal and {:?} <= {:?}", - stamp, max, stamp_mtime)); - return deps.into_iter().map(|(d, _)| d).collect() - } - if max > stamp_mtime { - builder.verbose(&format!("updating {:?} as {:?} changed", stamp, max_path)); - } else { - builder.verbose(&format!("updating {:?} as deps changed", stamp)); - } t!(fs::write(&stamp, &new_contents)); deps.into_iter().map(|(d, _)| d).collect() } @@ -1256,8 +1222,12 @@ pub fn stream_cargo( } // Instruct Cargo to give us json messages on stdout, critically leaving // stderr as piped so we can get those pretty colors. - cargo.arg("--message-format").arg("json") - .stdout(Stdio::piped()); + let mut message_format = String::from("json-render-diagnostics"); + if let Some(s) = &builder.config.rustc_error_format { + message_format.push_str(",json-diagnostic-"); + message_format.push_str(s); + } + cargo.arg("--message-format").arg(message_format).stdout(Stdio::piped()); for arg in tail_args { cargo.arg(arg); @@ -1310,12 +1280,4 @@ pub enum CargoMessage<'a> { BuildScriptExecuted { package_id: Cow<'a, str>, }, - CompilerMessage { - message: ClippyMessage<'a> - } -} - -#[derive(Deserialize)] -pub struct ClippyMessage<'a> { - rendered: Cow<'a, str>, } diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index bd012a887c2..213ceb194a8 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -469,7 +469,6 @@ impl Step for Rustc { fn prepare_image(builder: &Builder<'_>, compiler: Compiler, image: &Path) { let host = compiler.host; let src = builder.sysroot(compiler); - let libdir = builder.rustc_libdir(compiler); // Copy rustc/rustdoc binaries t!(fs::create_dir_all(image.join("bin"))); @@ -481,11 +480,14 @@ impl Step for Rustc { // Copy runtime DLLs needed by the compiler if libdir_relative.to_str() != Some("bin") { + let libdir = builder.rustc_libdir(compiler); for entry in builder.read_dir(&libdir) { let name = entry.file_name(); if let Some(s) = name.to_str() { if is_dylib(s) { - builder.install(&entry.path(), &image.join(&libdir_relative), 0o644); + // Don't use custom libdir here because ^lib/ will be resolved again + // with installer + builder.install(&entry.path(), &image.join("lib"), 0o644); } } } @@ -493,8 +495,11 @@ impl Step for Rustc { // Copy over the codegen backends let backends_src = builder.sysroot_codegen_backends(compiler); - let backends_rel = backends_src.strip_prefix(&src).unwrap(); - let backends_dst = image.join(&backends_rel); + let backends_rel = backends_src.strip_prefix(&src).unwrap() + .strip_prefix(builder.sysroot_libdir_relative(compiler)).unwrap(); + // Don't use custom libdir here because ^lib/ will be resolved again with installer + let backends_dst = image.join("lib").join(&backends_rel); + t!(fs::create_dir_all(&backends_dst)); builder.cp_r(&backends_src, &backends_dst); diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in index 73d6fe532c8..e0a1f46078d 100644 --- a/src/bootstrap/mk/Makefile.in +++ b/src/bootstrap/mk/Makefile.in @@ -81,5 +81,14 @@ ci-subset-1: ci-subset-2: $(Q)$(BOOTSTRAP) test $(TESTS_IN_2) +TESTS_IN_MINGW_2 := \ + src/test/ui \ + src/test/compile-fail + +ci-mingw-subset-1: + $(Q)$(BOOTSTRAP) test $(TESTS_IN_MINGW_2:%=--exclude %) +ci-mingw-subset-2: + $(Q)$(BOOTSTRAP) test $(TESTS_IN_MINGW_2) + .PHONY: dist diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index 4e3930c8da7..bffe748f37c 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -202,10 +202,6 @@ pub fn check(build: &mut Build) { panic!("couldn't find libc.a in musl dir: {}", root.join("lib").display()); } - if fs::metadata(root.join("lib/libunwind.a")).is_err() { - panic!("couldn't find libunwind.a in musl dir: {}", - root.join("lib").display()); - } } None => { panic!("when targeting MUSL either the rust.musl-root \ diff --git a/src/ci/azure-pipelines/auto.yml b/src/ci/azure-pipelines/auto.yml index 687856cca6b..77c9cda58b8 100644 --- a/src/ci/azure-pipelines/auto.yml +++ b/src/ci/azure-pipelines/auto.yml @@ -272,8 +272,8 @@ jobs: i686-mingw-1: MSYS_BITS: 32 RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu - SCRIPT: make ci-subset-1 - MINGW_URL: https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror + SCRIPT: make ci-mingw-subset-1 + MINGW_URL: https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z MINGW_DIR: mingw32 # FIXME(#59637) @@ -282,15 +282,15 @@ jobs: i686-mingw-2: MSYS_BITS: 32 RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu - SCRIPT: make ci-subset-2 - MINGW_URL: https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror + SCRIPT: make ci-mingw-subset-2 + MINGW_URL: https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z MINGW_DIR: mingw32 x86_64-mingw-1: MSYS_BITS: 64 - SCRIPT: make ci-subset-1 + SCRIPT: make ci-mingw-subset-1 RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu - MINGW_URL: https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror + MINGW_URL: https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z MINGW_DIR: mingw64 # FIXME(#59637) @@ -298,9 +298,9 @@ jobs: NO_LLVM_ASSERTIONS: 1 x86_64-mingw-2: MSYS_BITS: 64 - SCRIPT: make ci-subset-2 + SCRIPT: make ci-mingw-subset-2 RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu - MINGW_URL: https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror + MINGW_URL: https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z MINGW_DIR: mingw64 @@ -327,7 +327,7 @@ jobs: MSYS_BITS: 32 RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-full-tools --enable-profiler SCRIPT: python x.py dist - MINGW_URL: https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror + MINGW_URL: https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z MINGW_DIR: mingw32 DIST_REQUIRE_ALL_TOOLS: 1 @@ -336,7 +336,7 @@ jobs: MSYS_BITS: 64 SCRIPT: python x.py dist RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-full-tools --enable-profiler - MINGW_URL: https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror + MINGW_URL: https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z MINGW_DIR: mingw64 DIST_REQUIRE_ALL_TOOLS: 1 diff --git a/src/ci/azure-pipelines/steps/install-clang.yml b/src/ci/azure-pipelines/steps/install-clang.yml index 45ec767e0b8..14daf81b430 100644 --- a/src/ci/azure-pipelines/steps/install-clang.yml +++ b/src/ci/azure-pipelines/steps/install-clang.yml @@ -36,7 +36,7 @@ steps: set -e mkdir -p citools cd citools - curl -f https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/LLVM-7.0.0-win64.tar.gz | tar xzf - + curl -f https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/LLVM-7.0.0-win64.tar.gz | tar xzf - echo "##vso[task.setvariable variable=RUST_CONFIGURE_ARGS]$RUST_CONFIGURE_ARGS --set llvm.clang-cl=`pwd`/clang-rust/bin/clang-cl.exe" condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT'), eq(variables['MINGW_URL'],'')) displayName: Install clang (Windows) diff --git a/src/ci/azure-pipelines/steps/install-sccache.yml b/src/ci/azure-pipelines/steps/install-sccache.yml index 427e50f571f..d4679c1c673 100644 --- a/src/ci/azure-pipelines/steps/install-sccache.yml +++ b/src/ci/azure-pipelines/steps/install-sccache.yml @@ -2,14 +2,14 @@ steps: - bash: | set -e - curl -fo /usr/local/bin/sccache https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/2018-04-02-sccache-x86_64-apple-darwin + curl -fo /usr/local/bin/sccache https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/2018-04-02-sccache-x86_64-apple-darwin chmod +x /usr/local/bin/sccache displayName: Install sccache (OSX) condition: and(succeeded(), eq(variables['Agent.OS'], 'Darwin')) - script: | md sccache - powershell -Command "$ProgressPreference = 'SilentlyContinue'; iwr -outf sccache\sccache.exe https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/2018-04-26-sccache-x86_64-pc-windows-msvc" + powershell -Command "$ProgressPreference = 'SilentlyContinue'; iwr -outf sccache\sccache.exe https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/2018-04-26-sccache-x86_64-pc-windows-msvc" echo ##vso[task.prependpath]%CD%\sccache displayName: Install sccache (Windows) condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) 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 c42c2311b49..9aaeb4b79d6 100644 --- a/src/ci/azure-pipelines/steps/install-windows-build-deps.yml +++ b/src/ci/azure-pipelines/steps/install-windows-build-deps.yml @@ -4,7 +4,7 @@ steps: # https://github.com/wixtoolset/wix3 originally - bash: | set -e - curl -O https://rust-lang-ci2.s3-us-west-1.amazonaws.com/rust-ci-mirror/wix311-binaries.zip + curl -O https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/wix311-binaries.zip echo "##vso[task.setvariable variable=WIX]`pwd`/wix" mkdir -p wix/bin cd wix/bin @@ -18,7 +18,7 @@ steps: # one is MSI installers and one is EXE, but they're not used so frequently at # this point anyway so perhaps it's a wash! - script: | - powershell -Command "$ProgressPreference = 'SilentlyContinue'; iwr -outf is-install.exe https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/2017-08-22-is.exe" + powershell -Command "$ProgressPreference = 'SilentlyContinue'; iwr -outf is-install.exe https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/2017-08-22-is.exe" is-install.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP- echo ##vso[task.prependpath]C:\Program Files (x86)\Inno Setup 5 displayName: Install InnoSetup @@ -109,7 +109,7 @@ steps: # Note that this is originally from the github releases patch of Ninja - script: | md ninja - powershell -Command "$ProgressPreference = 'SilentlyContinue'; iwr -outf 2017-03-15-ninja-win.zip https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/2017-03-15-ninja-win.zip" + powershell -Command "$ProgressPreference = 'SilentlyContinue'; iwr -outf 2017-03-15-ninja-win.zip https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/2017-03-15-ninja-win.zip" 7z x -oninja 2017-03-15-ninja-win.zip del 2017-03-15-ninja-win.zip set RUST_CONFIGURE_ARGS=%RUST_CONFIGURE_ARGS% --enable-ninja diff --git a/src/ci/azure-pipelines/steps/run.yml b/src/ci/azure-pipelines/steps/run.yml index ca32888b74c..ac6b344a45e 100644 --- a/src/ci/azure-pipelines/steps/run.yml +++ b/src/ci/azure-pipelines/steps/run.yml @@ -199,7 +199,7 @@ steps: # Upload CPU usage statistics that we've been gathering this whole time. Always # execute this step in case we want to inspect failed builds, but don't let # errors here ever fail the build since this is just informational. -- bash: aws s3 cp --acl public-read cpu-usage.csv s3://$DEPLOY_BUCKET/rustc-builds/$BUILD_SOURCEVERSION/cpu-$SYSTEM_JOBNAME.csv +- bash: aws s3 cp --acl public-read cpu-usage.csv s3://$DEPLOY_BUCKET/rustc-builds/$BUILD_SOURCEVERSION/cpu-$CI_JOB_NAME.csv env: AWS_SECRET_ACCESS_KEY: $(AWS_SECRET_ACCESS_KEY) condition: variables['AWS_SECRET_ACCESS_KEY'] diff --git a/src/ci/docker/armhf-gnu/Dockerfile b/src/ci/docker/armhf-gnu/Dockerfile index 235920833f8..9493b336987 100644 --- a/src/ci/docker/armhf-gnu/Dockerfile +++ b/src/ci/docker/armhf-gnu/Dockerfile @@ -72,7 +72,7 @@ RUN arm-linux-gnueabihf-gcc addentropy.c -o rootfs/addentropy -static # TODO: What is this?! # Source of the file: https://github.com/vfdev-5/qemu-rpi2-vexpress/raw/master/vexpress-v2p-ca15-tc1.dtb -RUN curl -O https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/vexpress-v2p-ca15-tc1.dtb +RUN curl -O https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/vexpress-v2p-ca15-tc1.dtb COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh diff --git a/src/ci/docker/dist-various-1/install-mips-musl.sh b/src/ci/docker/dist-various-1/install-mips-musl.sh index 60a96e3b8e9..29cfb5d9608 100755 --- a/src/ci/docker/dist-various-1/install-mips-musl.sh +++ b/src/ci/docker/dist-various-1/install-mips-musl.sh @@ -5,7 +5,7 @@ mkdir /usr/local/mips-linux-musl # originally from # https://downloads.openwrt.org/snapshots/trunk/ar71xx/generic/ # OpenWrt-Toolchain-ar71xx-generic_gcc-5.3.0_musl-1.1.16.Linux-x86_64.tar.bz2 -URL="https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror" +URL="https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc" FILE="OpenWrt-Toolchain-ar71xx-generic_gcc-5.3.0_musl-1.1.16.Linux-x86_64.tar.bz2" curl -L "$URL/$FILE" | tar xjf - -C /usr/local/mips-linux-musl --strip-components=2 diff --git a/src/ci/docker/dist-various-2/build-wasi-toolchain.sh b/src/ci/docker/dist-various-2/build-wasi-toolchain.sh index 7bf8946c4f1..f04ee781571 100755 --- a/src/ci/docker/dist-various-2/build-wasi-toolchain.sh +++ b/src/ci/docker/dist-various-2/build-wasi-toolchain.sh @@ -5,7 +5,7 @@ set -ex # Originally from https://releases.llvm.org/8.0.0/clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-14.04.tar.xz -curl https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/clang%2Bllvm-8.0.0-x86_64-linux-gnu-ubuntu-14.04.tar.xz | \ +curl https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/clang%2Bllvm-8.0.0-x86_64-linux-gnu-ubuntu-14.04.tar.xz | \ tar xJf - export PATH=`pwd`/clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-14.04/bin:$PATH diff --git a/src/ci/docker/dist-x86_64-linux/build-openssl.sh b/src/ci/docker/dist-x86_64-linux/build-openssl.sh index 13dae616905..be8a6c93945 100755 --- a/src/ci/docker/dist-x86_64-linux/build-openssl.sh +++ b/src/ci/docker/dist-x86_64-linux/build-openssl.sh @@ -4,7 +4,7 @@ set -ex source shared.sh VERSION=1.0.2k -URL=https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/openssl-$VERSION.tar.gz +URL=https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/openssl-$VERSION.tar.gz curl $URL | tar xzf - diff --git a/src/ci/docker/dist-x86_64-netbsd/build-netbsd-toolchain.sh b/src/ci/docker/dist-x86_64-netbsd/build-netbsd-toolchain.sh index 2e9b9dcc234..797f674b954 100755 --- a/src/ci/docker/dist-x86_64-netbsd/build-netbsd-toolchain.sh +++ b/src/ci/docker/dist-x86_64-netbsd/build-netbsd-toolchain.sh @@ -25,7 +25,7 @@ cd netbsd mkdir -p /x-tools/x86_64-unknown-netbsd/sysroot -URL=https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror +URL=https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc # Originally from ftp://ftp.netbsd.org/pub/NetBSD/NetBSD-$BSD/source/sets/*.tgz curl $URL/2018-03-01-netbsd-src.tgz | tar xzf - diff --git a/src/ci/docker/scripts/android-sdk-manager.py b/src/ci/docker/scripts/android-sdk-manager.py index 7c9a8b82e92..c9e2961f6eb 100755 --- a/src/ci/docker/scripts/android-sdk-manager.py +++ b/src/ci/docker/scripts/android-sdk-manager.py @@ -23,8 +23,9 @@ REPOSITORIES = [ HOST_OS = "linux" # Mirroring options -MIRROR_BUCKET = "rust-lang-ci2" -MIRROR_BASE_DIR = "rust-ci-mirror/android/" +MIRROR_BUCKET = "rust-lang-ci-mirrors" +MIRROR_BUCKET_REGION = "us-west-1" +MIRROR_BASE_DIR = "rustc/android/" import argparse import hashlib @@ -144,7 +145,8 @@ def cli_install(args): lockfile = Lockfile(args.lockfile) for package in lockfile.packages.values(): # Download the file from the mirror into a temp file - url = "https://" + MIRROR_BUCKET + ".s3.amazonaws.com/" + MIRROR_BASE_DIR + url = "https://" + MIRROR_BUCKET + ".s3-" + MIRROR_BUCKET_REGION + \ + ".amazonaws.com/" + MIRROR_BASE_DIR downloaded = package.download(url) # Extract the file in a temporary directory extract_dir = tempfile.mkdtemp() diff --git a/src/ci/docker/scripts/freebsd-toolchain.sh b/src/ci/docker/scripts/freebsd-toolchain.sh index 8cef69d9c26..70155e770a9 100755 --- a/src/ci/docker/scripts/freebsd-toolchain.sh +++ b/src/ci/docker/scripts/freebsd-toolchain.sh @@ -59,7 +59,7 @@ done # Originally downloaded from: # https://download.freebsd.org/ftp/releases/${freebsd_arch}/${freebsd_version}-RELEASE/base.txz -URL=https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/2019-04-04-freebsd-${freebsd_arch}-${freebsd_version}-RELEASE-base.txz +URL=https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/2019-04-04-freebsd-${freebsd_arch}-${freebsd_version}-RELEASE-base.txz curl "$URL" | tar xJf - -C "$sysroot" --wildcards "${files_to_extract[@]}" # Fix up absolute symlinks from the system image. This can be removed diff --git a/src/ci/docker/scripts/musl-toolchain.sh b/src/ci/docker/scripts/musl-toolchain.sh index 55899fa6c3e..74ba2f0eadb 100644 --- a/src/ci/docker/scripts/musl-toolchain.sh +++ b/src/ci/docker/scripts/musl-toolchain.sh @@ -54,29 +54,3 @@ if [ "$REPLACE_CC" = "1" ]; then ln -s $TARGET-g++ /usr/local/bin/$exec done fi - -export CC=$TARGET-gcc -export CXX=$TARGET-g++ - -LLVM=70 - -# may have been downloaded in a previous run -if [ ! -d libunwind-release_$LLVM ]; then - curl -L https://github.com/llvm-mirror/llvm/archive/release_$LLVM.tar.gz | tar xzf - - curl -L https://github.com/llvm-mirror/libunwind/archive/release_$LLVM.tar.gz | tar xzf - -fi - -# fixme(mati865): Replace it with https://github.com/rust-lang/rust/pull/59089 -mkdir libunwind-build -cd libunwind-build -cmake ../libunwind-release_$LLVM \ - -DLLVM_PATH=/build/llvm-release_$LLVM \ - -DLIBUNWIND_ENABLE_SHARED=0 \ - -DCMAKE_C_COMPILER=$CC \ - -DCMAKE_CXX_COMPILER=$CXX \ - -DCMAKE_C_FLAGS="$CFLAGS" \ - -DCMAKE_CXX_FLAGS="$CXXFLAGS" - -hide_output make -j$(nproc) -cp lib/libunwind.a $OUTPUT/$TARGET/lib -cd - && rm -rf libunwind-build diff --git a/src/ci/docker/scripts/musl.sh b/src/ci/docker/scripts/musl.sh index c2cf77d56cb..d847c407aba 100644 --- a/src/ci/docker/scripts/musl.sh +++ b/src/ci/docker/scripts/musl.sh @@ -20,6 +20,8 @@ exit 1 TAG=$1 shift +# Ancient binutils versions don't understand debug symbols produced by more recent tools. +# Apparently applying `-fPIC` everywhere allows them to link successfully. export CFLAGS="-fPIC $CFLAGS" MUSL=musl-1.1.22 @@ -38,27 +40,3 @@ else fi hide_output make install hide_output make clean - -cd .. - -LLVM=70 - -# may have been downloaded in a previous run -if [ ! -d libunwind-release_$LLVM ]; then - curl -L https://github.com/llvm-mirror/llvm/archive/release_$LLVM.tar.gz | tar xzf - - curl -L https://github.com/llvm-mirror/libunwind/archive/release_$LLVM.tar.gz | tar xzf - -fi - -mkdir libunwind-build -cd libunwind-build -cmake ../libunwind-release_$LLVM \ - -DLLVM_PATH=/build/llvm-release_$LLVM \ - -DLIBUNWIND_ENABLE_SHARED=0 \ - -DCMAKE_C_COMPILER=$CC \ - -DCMAKE_CXX_COMPILER=$CXX \ - -DCMAKE_C_FLAGS="$CFLAGS" \ - -DCMAKE_CXX_FLAGS="$CXXFLAGS" - -hide_output make -j$(nproc) -cp lib/libunwind.a /musl-$TAG/lib -cd ../ && rm -rf libunwind-build diff --git a/src/ci/docker/scripts/sccache.sh b/src/ci/docker/scripts/sccache.sh index 194de3c339f..efeb0ed0d72 100644 --- a/src/ci/docker/scripts/sccache.sh +++ b/src/ci/docker/scripts/sccache.sh @@ -1,6 +1,6 @@ set -ex curl -fo /usr/local/bin/sccache \ - https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/2018-04-02-sccache-x86_64-unknown-linux-musl + https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/2018-04-02-sccache-x86_64-unknown-linux-musl chmod +x /usr/local/bin/sccache diff --git a/src/ci/install-awscli.sh b/src/ci/install-awscli.sh index d491b9fbcdc..69c8d2e3099 100755 --- a/src/ci/install-awscli.sh +++ b/src/ci/install-awscli.sh @@ -16,7 +16,7 @@ set -euo pipefail IFS=$'\n\t' -MIRROR="https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/2019-07-27-awscli.tar" +MIRROR="https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/2019-07-27-awscli.tar" DEPS_DIR="/tmp/awscli-deps" pip="pip" diff --git a/src/ci/run.sh b/src/ci/run.sh index f1eb417cdf9..457ba971712 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -78,6 +78,21 @@ if [ "$RUST_RELEASE_CHANNEL" = "nightly" ] || [ "$DIST_REQUIRE_ALL_TOOLS" = "" ] RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-missing-tools" fi +# Print the date from the local machine and the date from an external source to +# check for clock drifts. An HTTP URL is used instead of HTTPS since on Azure +# Pipelines it happened that the certificates were marked as expired. +datecheck() { + echo "== clock drift check ==" + echo -n " local time: " + date + echo -n " network time: " + curl -fs --head http://detectportal.firefox.com/success.txt | grep ^Date: \ + | sed 's/Date: //g' || true + echo "== end clock drift check ==" +} +datecheck +trap datecheck EXIT + # We've had problems in the past of shell scripts leaking fds into the sccache # server (#48192) which causes Cargo to erroneously think that a build script # hasn't finished yet. Try to solve that problem by starting a very long-lived diff --git a/src/doc/rustc-ux-guidelines.md b/src/doc/rustc-ux-guidelines.md index e3684fc9f32..dfd8e9db3c5 100644 --- a/src/doc/rustc-ux-guidelines.md +++ b/src/doc/rustc-ux-guidelines.md @@ -70,7 +70,7 @@ for details on how to format and write long error codes. [librustc_privacy](https://github.com/rust-lang/rust/blob/master/src/librustc_privacy/error_codes.rs), [librustc_resolve](https://github.com/rust-lang/rust/blob/master/src/librustc_resolve/error_codes.rs), [librustc_codegen_llvm](https://github.com/rust-lang/rust/blob/master/src/librustc_codegen_llvm/error_codes.rs), - [librustc_plugin](https://github.com/rust-lang/rust/blob/master/src/librustc_plugin/error_codes.rs), + [librustc_plugin_impl](https://github.com/rust-lang/rust/blob/master/src/librustc_plugin/error_codes.rs), [librustc_typeck](https://github.com/rust-lang/rust/blob/master/src/librustc_typeck/error_codes.rs). * Explanations have full markdown support. Use it, especially to highlight code with backticks. diff --git a/src/doc/unstable-book/src/language-features/or-patterns.md b/src/doc/unstable-book/src/language-features/or-patterns.md new file mode 100644 index 00000000000..8ebacb44d37 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/or-patterns.md @@ -0,0 +1,36 @@ +# `or_patterns` + +The tracking issue for this feature is: [#54883] + +[#54883]: https://github.com/rust-lang/rust/issues/54883 + +------------------------ + +The `or_pattern` language feature allows `|` to be arbitrarily nested within +a pattern, for example, `Some(A(0) | B(1 | 2))` becomes a valid pattern. + +## Examples + +```rust,ignore +#![feature(or_patterns)] + +pub enum Foo { + Bar, + Baz, + Quux, +} + +pub fn example(maybe_foo: Option<Foo>) { + match maybe_foo { + Some(Foo::Bar | Foo::Baz) => { + println!("The value contained `Bar` or `Baz`"); + } + Some(_) => { + println!("The value did not contain `Bar` or `Baz`"); + } + None => { + println!("The value was `None`"); + } + } +} +``` diff --git a/src/doc/unstable-book/src/language-features/plugin.md b/src/doc/unstable-book/src/language-features/plugin.md index 8be4d169982..53e8393ec52 100644 --- a/src/doc/unstable-book/src/language-features/plugin.md +++ b/src/doc/unstable-book/src/language-features/plugin.md @@ -18,7 +18,7 @@ extend the compiler's behavior with new syntax extensions, lint checks, etc. A plugin is a dynamic library crate with a designated *registrar* function that registers extensions with `rustc`. Other crates can load these extensions using the crate attribute `#![plugin(...)]`. See the -`rustc_plugin` documentation for more about the +`rustc_driver::plugin` documentation for more about the mechanics of defining and loading a plugin. If present, arguments passed as `#![plugin(foo(... args ...))]` are not @@ -54,13 +54,13 @@ that implements Roman numeral integer literals. extern crate syntax; extern crate syntax_pos; extern crate rustc; -extern crate rustc_plugin; +extern crate rustc_driver; use syntax::parse::token::{self, Token}; use syntax::tokenstream::TokenTree; use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacEager}; use syntax_pos::Span; -use rustc_plugin::Registry; +use rustc_driver::plugin::Registry; fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) -> Box<dyn MacResult + 'static> { @@ -180,11 +180,11 @@ extern crate syntax; // Load rustc as a plugin to get macros #[macro_use] extern crate rustc; -extern crate rustc_plugin; +extern crate rustc_driver; use rustc::lint::{EarlyContext, LintContext, LintPass, EarlyLintPass, EarlyLintPassObject, LintArray}; -use rustc_plugin::Registry; +use rustc_driver::plugin::Registry; use syntax::ast; declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'"); diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index c92db517cad..c61e3183409 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -91,8 +91,10 @@ use core::ops::{ CoerceUnsized, DispatchFromDyn, Deref, DerefMut, Receiver, Generator, GeneratorState }; use core::ptr::{self, NonNull, Unique}; +use core::slice; use core::task::{Context, Poll}; +use crate::alloc::{self, Global, Alloc}; use crate::vec::Vec; use crate::raw_vec::RawVec; use crate::str::from_boxed_utf8_unchecked; @@ -121,6 +123,34 @@ impl<T> Box<T> { box x } + /// Constructs a new box with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// + /// let mut five = Box::<u32>::new_uninit(); + /// + /// let five = unsafe { + /// // Deferred initialization: + /// five.as_mut_ptr().write(5); + /// + /// five.assume_init() + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + pub fn new_uninit() -> Box<mem::MaybeUninit<T>> { + let layout = alloc::Layout::new::<mem::MaybeUninit<T>>(); + let ptr = unsafe { + Global.alloc(layout) + .unwrap_or_else(|_| alloc::handle_alloc_error(layout)) + }; + Box(ptr.cast().into()) + } + /// Constructs a new `Pin<Box<T>>`. If `T` does not implement `Unpin`, then /// `x` will be pinned in memory and unable to be moved. #[stable(feature = "pin", since = "1.33.0")] @@ -130,6 +160,111 @@ impl<T> Box<T> { } } +impl<T> Box<[T]> { + /// Constructs a new boxed slice with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// + /// let mut values = Box::<[u32]>::new_uninit_slice(3); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// values[0].as_mut_ptr().write(1); + /// values[1].as_mut_ptr().write(2); + /// values[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + pub fn new_uninit_slice(len: usize) -> Box<[mem::MaybeUninit<T>]> { + let layout = alloc::Layout::array::<mem::MaybeUninit<T>>(len).unwrap(); + let ptr = unsafe { alloc::alloc(layout) }; + let unique = Unique::new(ptr).unwrap_or_else(|| alloc::handle_alloc_error(layout)); + let slice = unsafe { slice::from_raw_parts_mut(unique.cast().as_ptr(), len) }; + Box(Unique::from(slice)) + } +} + +impl<T> Box<mem::MaybeUninit<T>> { + /// Converts to `Box<T>`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the value + /// really is in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// [`MaybeUninit::assume_init`]: ../../std/mem/union.MaybeUninit.html#method.assume_init + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// + /// let mut five = Box::<u32>::new_uninit(); + /// + /// let five: Box<u32> = unsafe { + /// // Deferred initialization: + /// five.as_mut_ptr().write(5); + /// + /// five.assume_init() + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + #[inline] + pub unsafe fn assume_init(self) -> Box<T> { + Box(Box::into_unique(self).cast()) + } +} + +impl<T> Box<[mem::MaybeUninit<T>]> { + /// Converts to `Box<[T]>`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the values + /// really are in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// [`MaybeUninit::assume_init`]: ../../std/mem/union.MaybeUninit.html#method.assume_init + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// + /// let mut values = Box::<[u32]>::new_uninit_slice(3); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// values[0].as_mut_ptr().write(1); + /// values[1].as_mut_ptr().write(2); + /// values[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + #[inline] + pub unsafe fn assume_init(self) -> Box<[T]> { + Box(Unique::new_unchecked(Box::into_raw(self) as _)) + } +} + impl<T: ?Sized> Box<T> { /// Constructs a box from a raw pointer. /// diff --git a/src/liballoc/collections/binary_heap.rs b/src/liballoc/collections/binary_heap.rs index 9f531f5b83c..3d04f30e7bd 100644 --- a/src/liballoc/collections/binary_heap.rs +++ b/src/liballoc/collections/binary_heap.rs @@ -1163,6 +1163,9 @@ impl<T> FusedIterator for Drain<'_, T> {} #[stable(feature = "binary_heap_extras_15", since = "1.5.0")] impl<T: Ord> From<Vec<T>> for BinaryHeap<T> { + /// Converts a `Vec<T>` into a `BinaryHeap<T>`. + /// + /// This conversion happens in-place, and has `O(n)` time complexity. fn from(vec: Vec<T>) -> BinaryHeap<T> { let mut heap = BinaryHeap { data: vec }; heap.rebuild(); diff --git a/src/liballoc/collections/btree/node.rs b/src/liballoc/collections/btree/node.rs index e067096f0c7..0b5a271dbea 100644 --- a/src/liballoc/collections/btree/node.rs +++ b/src/liballoc/collections/btree/node.rs @@ -106,8 +106,8 @@ impl<K, V> LeafNode<K, V> { LeafNode { // As a general policy, we leave fields uninitialized if they can be, as this should // be both slightly faster and easier to track in Valgrind. - keys: uninit_array![_; CAPACITY], - vals: uninit_array![_; CAPACITY], + keys: [MaybeUninit::UNINIT; CAPACITY], + vals: [MaybeUninit::UNINIT; CAPACITY], parent: ptr::null(), parent_idx: MaybeUninit::uninit(), len: 0 @@ -159,7 +159,7 @@ impl<K, V> InternalNode<K, V> { unsafe fn new() -> Self { InternalNode { data: LeafNode::new(), - edges: uninit_array![_; 2*B], + edges: [MaybeUninit::UNINIT; 2*B] } } } diff --git a/src/liballoc/collections/mod.rs b/src/liballoc/collections/mod.rs index 5a33ddc14f0..f1f22fe48c5 100644 --- a/src/liballoc/collections/mod.rs +++ b/src/liballoc/collections/mod.rs @@ -41,32 +41,35 @@ pub use linked_list::LinkedList; #[doc(no_inline)] pub use vec_deque::VecDeque; -use crate::alloc::{AllocErr, LayoutErr}; +use crate::alloc::{Layout, LayoutErr}; -/// Augments `AllocErr` with a CapacityOverflow variant. +/// The error type for `try_reserve` methods. #[derive(Clone, PartialEq, Eq, Debug)] #[unstable(feature = "try_reserve", reason = "new API", issue="48043")] -pub enum CollectionAllocErr { +pub enum TryReserveError { /// Error due to the computed capacity exceeding the collection's maximum /// (usually `isize::MAX` bytes). CapacityOverflow, - /// Error due to the allocator (see the `AllocErr` type's docs). - AllocErr, -} -#[unstable(feature = "try_reserve", reason = "new API", issue="48043")] -impl From<AllocErr> for CollectionAllocErr { - #[inline] - fn from(AllocErr: AllocErr) -> Self { - CollectionAllocErr::AllocErr - } + /// The memory allocator returned an error + AllocError { + /// The layout of allocation request that failed + layout: Layout, + + #[doc(hidden)] + #[unstable(feature = "container_error_extra", issue = "0", reason = "\ + Enable exposing the allocator’s custom error value \ + if an associated type is added in the future: \ + https://github.com/rust-lang/wg-allocators/issues/23")] + non_exhaustive: (), + }, } #[unstable(feature = "try_reserve", reason = "new API", issue="48043")] -impl From<LayoutErr> for CollectionAllocErr { +impl From<LayoutErr> for TryReserveError { #[inline] fn from(_: LayoutErr) -> Self { - CollectionAllocErr::CapacityOverflow + TryReserveError::CapacityOverflow } } diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index 9240346ace9..7315963cc8b 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -18,7 +18,7 @@ use core::ptr::{self, NonNull}; use core::slice; use core::hash::{Hash, Hasher}; -use crate::collections::CollectionAllocErr; +use crate::collections::TryReserveError; use crate::raw_vec::RawVec; use crate::vec::Vec; @@ -576,10 +576,10 @@ impl<T> VecDeque<T> { /// /// ``` /// #![feature(try_reserve)] - /// use std::collections::CollectionAllocErr; + /// use std::collections::TryReserveError; /// use std::collections::VecDeque; /// - /// fn process_data(data: &[u32]) -> Result<VecDeque<u32>, CollectionAllocErr> { + /// fn process_data(data: &[u32]) -> Result<VecDeque<u32>, TryReserveError> { /// let mut output = VecDeque::new(); /// /// // Pre-reserve the memory, exiting if we can't @@ -595,7 +595,7 @@ impl<T> VecDeque<T> { /// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?"); /// ``` #[unstable(feature = "try_reserve", reason = "new API", issue="48043")] - pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), CollectionAllocErr> { + pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { self.try_reserve(additional) } @@ -614,10 +614,10 @@ impl<T> VecDeque<T> { /// /// ``` /// #![feature(try_reserve)] - /// use std::collections::CollectionAllocErr; + /// use std::collections::TryReserveError; /// use std::collections::VecDeque; /// - /// fn process_data(data: &[u32]) -> Result<VecDeque<u32>, CollectionAllocErr> { + /// fn process_data(data: &[u32]) -> Result<VecDeque<u32>, TryReserveError> { /// let mut output = VecDeque::new(); /// /// // Pre-reserve the memory, exiting if we can't @@ -633,12 +633,12 @@ impl<T> VecDeque<T> { /// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?"); /// ``` #[unstable(feature = "try_reserve", reason = "new API", issue="48043")] - pub fn try_reserve(&mut self, additional: usize) -> Result<(), CollectionAllocErr> { + pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { let old_cap = self.cap(); let used_cap = self.len() + 1; let new_cap = used_cap.checked_add(additional) .and_then(|needed_cap| needed_cap.checked_next_power_of_two()) - .ok_or(CollectionAllocErr::CapacityOverflow)?; + .ok_or(TryReserveError::CapacityOverflow)?; if new_cap > old_cap { self.buf.try_reserve_exact(used_cap, new_cap - used_cap)?; @@ -1199,6 +1199,31 @@ impl<T> VecDeque<T> { } } + /// Removes the last element from the `VecDeque` and returns it, or `None` if + /// it is empty. + /// + /// # Examples + /// + /// ``` + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::new(); + /// assert_eq!(buf.pop_back(), None); + /// buf.push_back(1); + /// buf.push_back(3); + /// assert_eq!(buf.pop_back(), Some(3)); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn pop_back(&mut self) -> Option<T> { + if self.is_empty() { + None + } else { + self.head = self.wrap_sub(self.head, 1); + let head = self.head; + unsafe { Some(self.buffer_read(head)) } + } + } + /// Prepends an element to the `VecDeque`. /// /// # Examples @@ -1243,38 +1268,13 @@ impl<T> VecDeque<T> { unsafe { self.buffer_write(head, value) } } - /// Removes the last element from the `VecDeque` and returns it, or `None` if - /// it is empty. - /// - /// # Examples - /// - /// ``` - /// use std::collections::VecDeque; - /// - /// let mut buf = VecDeque::new(); - /// assert_eq!(buf.pop_back(), None); - /// buf.push_back(1); - /// buf.push_back(3); - /// assert_eq!(buf.pop_back(), Some(3)); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn pop_back(&mut self) -> Option<T> { - if self.is_empty() { - None - } else { - self.head = self.wrap_sub(self.head, 1); - let head = self.head; - unsafe { Some(self.buffer_read(head)) } - } - } - #[inline] fn is_contiguous(&self) -> bool { self.tail <= self.head } - /// Removes an element from anywhere in the `VecDeque` and returns it, replacing it with the - /// last element. + /// Removes an element from anywhere in the `VecDeque` and returns it, + /// replacing it with the first element. /// /// This does not preserve ordering, but is O(1). /// @@ -1288,28 +1288,28 @@ impl<T> VecDeque<T> { /// use std::collections::VecDeque; /// /// let mut buf = VecDeque::new(); - /// assert_eq!(buf.swap_remove_back(0), None); + /// assert_eq!(buf.swap_remove_front(0), None); /// buf.push_back(1); /// buf.push_back(2); /// buf.push_back(3); /// assert_eq!(buf, [1, 2, 3]); /// - /// assert_eq!(buf.swap_remove_back(0), Some(1)); - /// assert_eq!(buf, [3, 2]); + /// assert_eq!(buf.swap_remove_front(2), Some(3)); + /// assert_eq!(buf, [2, 1]); /// ``` #[stable(feature = "deque_extras_15", since = "1.5.0")] - pub fn swap_remove_back(&mut self, index: usize) -> Option<T> { + pub fn swap_remove_front(&mut self, index: usize) -> Option<T> { let length = self.len(); - if length > 0 && index < length - 1 { - self.swap(index, length - 1); + if length > 0 && index < length && index != 0 { + self.swap(index, 0); } else if index >= length { return None; } - self.pop_back() + self.pop_front() } - /// Removes an element from anywhere in the `VecDeque` and returns it, - /// replacing it with the first element. + /// Removes an element from anywhere in the `VecDeque` and returns it, replacing it with the + /// last element. /// /// This does not preserve ordering, but is O(1). /// @@ -1323,24 +1323,24 @@ impl<T> VecDeque<T> { /// use std::collections::VecDeque; /// /// let mut buf = VecDeque::new(); - /// assert_eq!(buf.swap_remove_front(0), None); + /// assert_eq!(buf.swap_remove_back(0), None); /// buf.push_back(1); /// buf.push_back(2); /// buf.push_back(3); /// assert_eq!(buf, [1, 2, 3]); /// - /// assert_eq!(buf.swap_remove_front(2), Some(3)); - /// assert_eq!(buf, [2, 1]); + /// assert_eq!(buf.swap_remove_back(0), Some(1)); + /// assert_eq!(buf, [3, 2]); /// ``` #[stable(feature = "deque_extras_15", since = "1.5.0")] - pub fn swap_remove_front(&mut self, index: usize) -> Option<T> { + pub fn swap_remove_back(&mut self, index: usize) -> Option<T> { let length = self.len(); - if length > 0 && index < length && index != 0 { - self.swap(index, 0); + if length > 0 && index < length - 1 { + self.swap(index, length - 1); } else if index >= length { return None; } - self.pop_front() + self.pop_back() } /// Inserts an element at `index` within the `VecDeque`, shifting all elements with indices diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index a1936b36ac6..4a48945adc3 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -69,7 +69,7 @@ #![warn(missing_debug_implementations)] #![deny(intra_doc_link_resolution_failure)] // rustdoc is run without -D warnings #![allow(explicit_outlives_requirements)] -#![cfg_attr(not(bootstrap), allow(incomplete_features))] +#![allow(incomplete_features)] #![cfg_attr(not(test), feature(generator_trait))] #![cfg_attr(test, feature(test))] @@ -84,9 +84,10 @@ #![feature(coerce_unsized)] #![feature(const_generic_impls_guard)] #![feature(const_generics)] -#![cfg_attr(not(bootstrap), feature(const_in_array_repeat_expressions))] +#![feature(const_in_array_repeat_expressions)] #![feature(dispatch_from_dyn)] #![feature(core_intrinsics)] +#![feature(container_error_extra)] #![feature(dropck_eyepatch)] #![feature(exact_size_is_empty)] #![feature(fmt_internals)] @@ -118,7 +119,7 @@ #![feature(rustc_const_unstable)] #![feature(const_vec_new)] #![feature(slice_partition_dedup)] -#![feature(maybe_uninit_extra, maybe_uninit_slice, maybe_uninit_array)] +#![feature(maybe_uninit_extra, maybe_uninit_slice)] #![feature(alloc_layout_extra)] #![feature(try_trait)] #![feature(mem_take)] diff --git a/src/liballoc/macros.rs b/src/liballoc/macros.rs index 250c419c531..0b5e186d4c7 100644 --- a/src/liballoc/macros.rs +++ b/src/liballoc/macros.rs @@ -98,5 +98,5 @@ macro_rules! vec { #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] macro_rules! format { - ($($arg:tt)*) => ($crate::fmt::format(format_args!($($arg)*))) + ($($arg:tt)*) => ($crate::fmt::format(::core::format_args!($($arg)*))) } diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index 0abab45e920..bc8a38f6b3a 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -7,8 +7,8 @@ use core::ops::Drop; use core::ptr::{self, NonNull, Unique}; use core::slice; -use crate::alloc::{Alloc, Layout, Global, handle_alloc_error}; -use crate::collections::CollectionAllocErr::{self, *}; +use crate::alloc::{Alloc, Layout, Global, AllocErr, handle_alloc_error}; +use crate::collections::TryReserveError::{self, *}; use crate::boxed::Box; #[cfg(test)] @@ -385,7 +385,7 @@ impl<T, A: Alloc> RawVec<T, A> { /// The same as `reserve_exact`, but returns on errors instead of panicking or aborting. pub fn try_reserve_exact(&mut self, used_capacity: usize, needed_extra_capacity: usize) - -> Result<(), CollectionAllocErr> { + -> Result<(), TryReserveError> { self.reserve_internal(used_capacity, needed_extra_capacity, Fallible, Exact) } @@ -413,7 +413,7 @@ impl<T, A: Alloc> RawVec<T, A> { pub fn reserve_exact(&mut self, used_capacity: usize, needed_extra_capacity: usize) { match self.reserve_internal(used_capacity, needed_extra_capacity, Infallible, Exact) { Err(CapacityOverflow) => capacity_overflow(), - Err(AllocErr) => unreachable!(), + Err(AllocError { .. }) => unreachable!(), Ok(()) => { /* yay */ } } } @@ -422,7 +422,7 @@ impl<T, A: Alloc> RawVec<T, A> { /// needed_extra_capacity` elements. This logic is used in amortized reserve methods. /// Returns `(new_capacity, new_alloc_size)`. fn amortized_new_size(&self, used_capacity: usize, needed_extra_capacity: usize) - -> Result<usize, CollectionAllocErr> { + -> Result<usize, TryReserveError> { // Nothing we can really do about these checks :( let required_cap = used_capacity.checked_add(needed_extra_capacity) @@ -435,7 +435,7 @@ impl<T, A: Alloc> RawVec<T, A> { /// The same as `reserve`, but returns on errors instead of panicking or aborting. pub fn try_reserve(&mut self, used_capacity: usize, needed_extra_capacity: usize) - -> Result<(), CollectionAllocErr> { + -> Result<(), TryReserveError> { self.reserve_internal(used_capacity, needed_extra_capacity, Fallible, Amortized) } @@ -494,7 +494,7 @@ impl<T, A: Alloc> RawVec<T, A> { pub fn reserve(&mut self, used_capacity: usize, needed_extra_capacity: usize) { match self.reserve_internal(used_capacity, needed_extra_capacity, Infallible, Amortized) { Err(CapacityOverflow) => capacity_overflow(), - Err(AllocErr) => unreachable!(), + Err(AllocError { .. }) => unreachable!(), Ok(()) => { /* yay */ } } } @@ -640,10 +640,8 @@ impl<T, A: Alloc> RawVec<T, A> { needed_extra_capacity: usize, fallibility: Fallibility, strategy: ReserveStrategy, - ) -> Result<(), CollectionAllocErr> { + ) -> Result<(), TryReserveError> { unsafe { - use crate::alloc::AllocErr; - // NOTE: we don't early branch on ZSTs here because we want this // to actually catch "asking for more than usize::MAX" in that case. // If we make it past the first branch then we are guaranteed to @@ -672,12 +670,16 @@ impl<T, A: Alloc> RawVec<T, A> { None => self.a.alloc(new_layout), }; - match (&res, fallibility) { + let ptr = match (res, fallibility) { (Err(AllocErr), Infallible) => handle_alloc_error(new_layout), - _ => {} - } + (Err(AllocErr), Fallible) => return Err(TryReserveError::AllocError { + layout: new_layout, + non_exhaustive: (), + }), + (Ok(ptr), _) => ptr, + }; - self.ptr = res?.cast().into(); + self.ptr = ptr.cast().into(); self.cap = new_cap; Ok(()) @@ -737,7 +739,7 @@ unsafe impl<#[may_dangle] T, A: Alloc> Drop for RawVec<T, A> { // all 4GB in user-space. e.g., PAE or x32 #[inline] -fn alloc_guard(alloc_size: usize) -> Result<(), CollectionAllocErr> { +fn alloc_guard(alloc_size: usize) -> Result<(), TryReserveError> { if mem::size_of::<usize>() < 8 && alloc_size > core::isize::MAX as usize { Err(CapacityOverflow) } else { diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 0c406a92029..2b222caf13f 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -327,6 +327,37 @@ impl<T> Rc<T> { })) } + /// Constructs a new `Rc` with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::rc::Rc; + /// + /// let mut five = Rc::<u32>::new_uninit(); + /// + /// let five = unsafe { + /// // Deferred initialization: + /// Rc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); + /// + /// five.assume_init() + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + pub fn new_uninit() -> Rc<mem::MaybeUninit<T>> { + unsafe { + Rc::from_ptr(Rc::allocate_for_layout( + Layout::new::<T>(), + |mem| mem as *mut RcBox<mem::MaybeUninit<T>>, + )) + } + } + /// Constructs a new `Pin<Rc<T>>`. If `T` does not implement `Unpin`, then /// `value` will be pinned in memory and unable to be moved. #[stable(feature = "pin", since = "1.33.0")] @@ -377,6 +408,118 @@ impl<T> Rc<T> { } } +impl<T> Rc<[T]> { + /// Constructs a new reference-counted slice with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::rc::Rc; + /// + /// let mut values = Rc::<[u32]>::new_uninit_slice(3); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// Rc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1); + /// Rc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2); + /// Rc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + pub fn new_uninit_slice(len: usize) -> Rc<[mem::MaybeUninit<T>]> { + unsafe { + Rc::from_ptr(Rc::allocate_for_slice(len)) + } + } +} + +impl<T> Rc<mem::MaybeUninit<T>> { + /// Converts to `Rc<T>`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the value + /// really is in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// [`MaybeUninit::assume_init`]: ../../std/mem/union.MaybeUninit.html#method.assume_init + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::rc::Rc; + /// + /// let mut five = Rc::<u32>::new_uninit(); + /// + /// let five = unsafe { + /// // Deferred initialization: + /// Rc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); + /// + /// five.assume_init() + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + #[inline] + pub unsafe fn assume_init(self) -> Rc<T> { + Rc::from_inner(mem::ManuallyDrop::new(self).ptr.cast()) + } +} + +impl<T> Rc<[mem::MaybeUninit<T>]> { + /// Converts to `Rc<[T]>`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the value + /// really is in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// [`MaybeUninit::assume_init`]: ../../std/mem/union.MaybeUninit.html#method.assume_init + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::rc::Rc; + /// + /// let mut values = Rc::<[u32]>::new_uninit_slice(3); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// Rc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1); + /// Rc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2); + /// Rc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + #[inline] + pub unsafe fn assume_init(self) -> Rc<[T]> { + Rc::from_ptr(mem::ManuallyDrop::new(self).ptr.as_ptr() as _) + } +} + impl<T: ?Sized> Rc<T> { /// Consumes the `Rc`, returning the wrapped pointer. /// @@ -560,13 +703,46 @@ impl<T: ?Sized> Rc<T> { pub fn get_mut(this: &mut Self) -> Option<&mut T> { if Rc::is_unique(this) { unsafe { - Some(&mut this.ptr.as_mut().value) + Some(Rc::get_mut_unchecked(this)) } } else { None } } + /// Returns a mutable reference to the inner value, + /// without any check. + /// + /// See also [`get_mut`], which is safe and does appropriate checks. + /// + /// [`get_mut`]: struct.Rc.html#method.get_mut + /// + /// # Safety + /// + /// Any other `Rc` or [`Weak`] pointers to the same value must not be dereferenced + /// for the duration of the returned borrow. + /// This is trivially the case if no such pointers exist, + /// for example immediately after `Rc::new`. + /// + /// # Examples + /// + /// ``` + /// #![feature(get_mut_unchecked)] + /// + /// use std::rc::Rc; + /// + /// let mut x = Rc::new(String::new()); + /// unsafe { + /// Rc::get_mut_unchecked(&mut x).push_str("foo") + /// } + /// assert_eq!(*x, "foo"); + /// ``` + #[inline] + #[unstable(feature = "get_mut_unchecked", issue = "63292")] + pub unsafe fn get_mut_unchecked(this: &mut Self) -> &mut T { + &mut this.ptr.as_mut().value + } + #[inline] #[stable(feature = "ptr_eq", since = "1.17.0")] /// Returns `true` if the two `Rc`s point to the same value (not @@ -704,11 +880,11 @@ impl Rc<dyn Any> { impl<T: ?Sized> Rc<T> { /// Allocates an `RcBox<T>` with sufficient space for - /// an unsized value where the value has the layout provided. + /// a possibly-unsized value where the value has the layout provided. /// /// The function `mem_to_rcbox` is called with the data pointer /// and must return back a (potentially fat)-pointer for the `RcBox<T>`. - unsafe fn allocate_for_unsized( + unsafe fn allocate_for_layout( value_layout: Layout, mem_to_rcbox: impl FnOnce(*mut u8) -> *mut RcBox<T> ) -> *mut RcBox<T> { @@ -737,7 +913,7 @@ impl<T: ?Sized> Rc<T> { /// Allocates an `RcBox<T>` with sufficient space for an unsized value unsafe fn allocate_for_ptr(ptr: *const T) -> *mut RcBox<T> { // Allocate for the `RcBox<T>` using the given value. - Self::allocate_for_unsized( + Self::allocate_for_layout( Layout::for_value(&*ptr), |mem| set_data_ptr(ptr as *mut T, mem) as *mut RcBox<T>, ) @@ -768,7 +944,7 @@ impl<T: ?Sized> Rc<T> { impl<T> Rc<[T]> { /// Allocates an `RcBox<[T]>` with the given length. unsafe fn allocate_for_slice(len: usize) -> *mut RcBox<[T]> { - Self::allocate_for_unsized( + Self::allocate_for_layout( Layout::array::<T>(len).unwrap(), |mem| ptr::slice_from_raw_parts_mut(mem as *mut T, len) as *mut RcBox<[T]>, ) diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index eca726cd410..b65f191836e 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -56,7 +56,7 @@ use core::ptr; use core::str::{pattern::Pattern, lossy}; use crate::borrow::{Cow, ToOwned}; -use crate::collections::CollectionAllocErr; +use crate::collections::TryReserveError; use crate::boxed::Box; use crate::str::{self, from_boxed_utf8_unchecked, FromStr, Utf8Error, Chars}; use crate::vec::Vec; @@ -937,9 +937,9 @@ impl String { /// /// ``` /// #![feature(try_reserve)] - /// use std::collections::CollectionAllocErr; + /// use std::collections::TryReserveError; /// - /// fn process_data(data: &str) -> Result<String, CollectionAllocErr> { + /// fn process_data(data: &str) -> Result<String, TryReserveError> { /// let mut output = String::new(); /// /// // Pre-reserve the memory, exiting if we can't @@ -953,7 +953,7 @@ impl String { /// # process_data("rust").expect("why is the test harness OOMing on 4 bytes?"); /// ``` #[unstable(feature = "try_reserve", reason = "new API", issue="48043")] - pub fn try_reserve(&mut self, additional: usize) -> Result<(), CollectionAllocErr> { + pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { self.vec.try_reserve(additional) } @@ -975,9 +975,9 @@ impl String { /// /// ``` /// #![feature(try_reserve)] - /// use std::collections::CollectionAllocErr; + /// use std::collections::TryReserveError; /// - /// fn process_data(data: &str) -> Result<String, CollectionAllocErr> { + /// fn process_data(data: &str) -> Result<String, TryReserveError> { /// let mut output = String::new(); /// /// // Pre-reserve the memory, exiting if we can't @@ -991,7 +991,7 @@ impl String { /// # process_data("rust").expect("why is the test harness OOMing on 4 bytes?"); /// ``` #[unstable(feature = "try_reserve", reason = "new API", issue="48043")] - pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), CollectionAllocErr> { + pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { self.vec.try_reserve_exact(additional) } diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 7d3b2656a7b..9ffc1673e5a 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -107,10 +107,6 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize; /// // a, b, and foo are all Arcs that point to the same memory location /// ``` /// -/// The [`Arc::clone(&from)`] syntax is the most idiomatic because it conveys more explicitly -/// the meaning of the code. In the example above, this syntax makes it easier to see that -/// this code is creating a new reference rather than copying the whole content of foo. -/// /// ## `Deref` behavior /// /// `Arc<T>` automatically dereferences to `T` (via the [`Deref`][deref] trait), @@ -311,6 +307,37 @@ impl<T> Arc<T> { Self::from_inner(Box::into_raw_non_null(x)) } + /// Constructs a new `Arc` with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let mut five = Arc::<u32>::new_uninit(); + /// + /// let five = unsafe { + /// // Deferred initialization: + /// Arc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); + /// + /// five.assume_init() + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + pub fn new_uninit() -> Arc<mem::MaybeUninit<T>> { + unsafe { + Arc::from_ptr(Arc::allocate_for_layout( + Layout::new::<T>(), + |mem| mem as *mut ArcInner<mem::MaybeUninit<T>>, + )) + } + } + /// Constructs a new `Pin<Arc<T>>`. If `T` does not implement `Unpin`, then /// `data` will be pinned in memory and unable to be moved. #[stable(feature = "pin", since = "1.33.0")] @@ -361,6 +388,118 @@ impl<T> Arc<T> { } } +impl<T> Arc<[T]> { + /// Constructs a new reference-counted slice with uninitialized contents. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let mut values = Arc::<[u32]>::new_uninit_slice(3); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// Arc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1); + /// Arc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2); + /// Arc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + pub fn new_uninit_slice(len: usize) -> Arc<[mem::MaybeUninit<T>]> { + unsafe { + Arc::from_ptr(Arc::allocate_for_slice(len)) + } + } +} + +impl<T> Arc<mem::MaybeUninit<T>> { + /// Converts to `Arc<T>`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the value + /// really is in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// [`MaybeUninit::assume_init`]: ../../std/mem/union.MaybeUninit.html#method.assume_init + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let mut five = Arc::<u32>::new_uninit(); + /// + /// let five = unsafe { + /// // Deferred initialization: + /// Arc::get_mut_unchecked(&mut five).as_mut_ptr().write(5); + /// + /// five.assume_init() + /// }; + /// + /// assert_eq!(*five, 5) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + #[inline] + pub unsafe fn assume_init(self) -> Arc<T> { + Arc::from_inner(mem::ManuallyDrop::new(self).ptr.cast()) + } +} + +impl<T> Arc<[mem::MaybeUninit<T>]> { + /// Converts to `Arc<[T]>`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the value + /// really is in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// [`MaybeUninit::assume_init`]: ../../std/mem/union.MaybeUninit.html#method.assume_init + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let mut values = Arc::<[u32]>::new_uninit_slice(3); + /// + /// let values = unsafe { + /// // Deferred initialization: + /// Arc::get_mut_unchecked(&mut values)[0].as_mut_ptr().write(1); + /// Arc::get_mut_unchecked(&mut values)[1].as_mut_ptr().write(2); + /// Arc::get_mut_unchecked(&mut values)[2].as_mut_ptr().write(3); + /// + /// values.assume_init() + /// }; + /// + /// assert_eq!(*values, [1, 2, 3]) + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + #[inline] + pub unsafe fn assume_init(self) -> Arc<[T]> { + Arc::from_ptr(mem::ManuallyDrop::new(self).ptr.as_ptr() as _) + } +} + impl<T: ?Sized> Arc<T> { /// Consumes the `Arc`, returning the wrapped pointer. /// @@ -593,11 +732,11 @@ impl<T: ?Sized> Arc<T> { impl<T: ?Sized> Arc<T> { /// Allocates an `ArcInner<T>` with sufficient space for - /// an unsized value where the value has the layout provided. + /// a possibly-unsized value where the value has the layout provided. /// /// The function `mem_to_arcinner` is called with the data pointer /// and must return back a (potentially fat)-pointer for the `ArcInner<T>`. - unsafe fn allocate_for_unsized( + unsafe fn allocate_for_layout( value_layout: Layout, mem_to_arcinner: impl FnOnce(*mut u8) -> *mut ArcInner<T> ) -> *mut ArcInner<T> { @@ -625,7 +764,7 @@ impl<T: ?Sized> Arc<T> { /// Allocates an `ArcInner<T>` with sufficient space for an unsized value. unsafe fn allocate_for_ptr(ptr: *const T) -> *mut ArcInner<T> { // Allocate for the `ArcInner<T>` using the given value. - Self::allocate_for_unsized( + Self::allocate_for_layout( Layout::for_value(&*ptr), |mem| set_data_ptr(ptr as *mut T, mem) as *mut ArcInner<T>, ) @@ -656,7 +795,7 @@ impl<T: ?Sized> Arc<T> { impl<T> Arc<[T]> { /// Allocates an `ArcInner<[T]>` with the given length. unsafe fn allocate_for_slice(len: usize) -> *mut ArcInner<[T]> { - Self::allocate_for_unsized( + Self::allocate_for_layout( Layout::array::<T>(len).unwrap(), |mem| ptr::slice_from_raw_parts_mut(mem as *mut T, len) as *mut ArcInner<[T]>, ) @@ -945,13 +1084,46 @@ impl<T: ?Sized> Arc<T> { // the Arc itself to be `mut`, so we're returning the only possible // reference to the inner data. unsafe { - Some(&mut this.ptr.as_mut().data) + Some(Arc::get_mut_unchecked(this)) } } else { None } } + /// Returns a mutable reference to the inner value, + /// without any check. + /// + /// See also [`get_mut`], which is safe and does appropriate checks. + /// + /// [`get_mut`]: struct.Arc.html#method.get_mut + /// + /// # Safety + /// + /// Any other `Arc` or [`Weak`] pointers to the same value must not be dereferenced + /// for the duration of the returned borrow. + /// This is trivially the case if no such pointers exist, + /// for example immediately after `Arc::new`. + /// + /// # Examples + /// + /// ``` + /// #![feature(get_mut_unchecked)] + /// + /// use std::sync::Arc; + /// + /// let mut x = Arc::new(String::new()); + /// unsafe { + /// Arc::get_mut_unchecked(&mut x).push_str("foo") + /// } + /// assert_eq!(*x, "foo"); + /// ``` + #[inline] + #[unstable(feature = "get_mut_unchecked", issue = "63292")] + pub unsafe fn get_mut_unchecked(this: &mut Self) -> &mut T { + &mut this.ptr.as_mut().data + } + /// Determine whether this is the unique reference (including weak refs) to /// the underlying data. /// diff --git a/src/liballoc/tests/string.rs b/src/liballoc/tests/string.rs index 765210e5aa6..55edf56345b 100644 --- a/src/liballoc/tests/string.rs +++ b/src/liballoc/tests/string.rs @@ -1,5 +1,5 @@ use std::borrow::Cow; -use std::collections::CollectionAllocErr::*; +use std::collections::TryReserveError::*; use std::mem::size_of; use std::{usize, isize}; @@ -566,11 +566,11 @@ fn test_try_reserve() { } else { panic!("usize::MAX should trigger an overflow!") } } else { // Check isize::MAX + 1 is an OOM - if let Err(AllocErr) = empty_string.try_reserve(MAX_CAP + 1) { + if let Err(AllocError { .. }) = empty_string.try_reserve(MAX_CAP + 1) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } // Check usize::MAX is an OOM - if let Err(AllocErr) = empty_string.try_reserve(MAX_USIZE) { + if let Err(AllocError { .. }) = empty_string.try_reserve(MAX_USIZE) { } else { panic!("usize::MAX should trigger an OOM!") } } } @@ -590,7 +590,7 @@ fn test_try_reserve() { if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 9) { } else { panic!("isize::MAX + 1 should trigger an overflow!"); } } else { - if let Err(AllocErr) = ten_bytes.try_reserve(MAX_CAP - 9) { + if let Err(AllocError { .. }) = ten_bytes.try_reserve(MAX_CAP - 9) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } } // Should always overflow in the add-to-len @@ -629,10 +629,10 @@ fn test_try_reserve_exact() { if let Err(CapacityOverflow) = empty_string.try_reserve_exact(MAX_USIZE) { } else { panic!("usize::MAX should trigger an overflow!") } } else { - if let Err(AllocErr) = empty_string.try_reserve_exact(MAX_CAP + 1) { + if let Err(AllocError { .. }) = empty_string.try_reserve_exact(MAX_CAP + 1) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } - if let Err(AllocErr) = empty_string.try_reserve_exact(MAX_USIZE) { + if let Err(AllocError { .. }) = empty_string.try_reserve_exact(MAX_USIZE) { } else { panic!("usize::MAX should trigger an OOM!") } } } @@ -651,7 +651,7 @@ fn test_try_reserve_exact() { if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { } else { panic!("isize::MAX + 1 should trigger an overflow!"); } } else { - if let Err(AllocErr) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { + if let Err(AllocError { .. }) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } } if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_USIZE) { diff --git a/src/liballoc/tests/vec.rs b/src/liballoc/tests/vec.rs index 6e8ffe18522..29a22aa0315 100644 --- a/src/liballoc/tests/vec.rs +++ b/src/liballoc/tests/vec.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use std::mem::size_of; use std::{usize, isize}; use std::vec::{Drain, IntoIter}; -use std::collections::CollectionAllocErr::*; +use std::collections::TryReserveError::*; struct DropCounter<'a> { count: &'a mut u32, @@ -1121,11 +1121,11 @@ fn test_try_reserve() { } else { panic!("usize::MAX should trigger an overflow!") } } else { // Check isize::MAX + 1 is an OOM - if let Err(AllocErr) = empty_bytes.try_reserve(MAX_CAP + 1) { + if let Err(AllocError { .. }) = empty_bytes.try_reserve(MAX_CAP + 1) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } // Check usize::MAX is an OOM - if let Err(AllocErr) = empty_bytes.try_reserve(MAX_USIZE) { + if let Err(AllocError { .. }) = empty_bytes.try_reserve(MAX_USIZE) { } else { panic!("usize::MAX should trigger an OOM!") } } } @@ -1145,7 +1145,7 @@ fn test_try_reserve() { if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 9) { } else { panic!("isize::MAX + 1 should trigger an overflow!"); } } else { - if let Err(AllocErr) = ten_bytes.try_reserve(MAX_CAP - 9) { + if let Err(AllocError { .. }) = ten_bytes.try_reserve(MAX_CAP - 9) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } } // Should always overflow in the add-to-len @@ -1168,7 +1168,7 @@ fn test_try_reserve() { if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP/4 - 9) { } else { panic!("isize::MAX + 1 should trigger an overflow!"); } } else { - if let Err(AllocErr) = ten_u32s.try_reserve(MAX_CAP/4 - 9) { + if let Err(AllocError { .. }) = ten_u32s.try_reserve(MAX_CAP/4 - 9) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } } // Should fail in the mul-by-size @@ -1209,10 +1209,10 @@ fn test_try_reserve_exact() { if let Err(CapacityOverflow) = empty_bytes.try_reserve_exact(MAX_USIZE) { } else { panic!("usize::MAX should trigger an overflow!") } } else { - if let Err(AllocErr) = empty_bytes.try_reserve_exact(MAX_CAP + 1) { + if let Err(AllocError { .. }) = empty_bytes.try_reserve_exact(MAX_CAP + 1) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } - if let Err(AllocErr) = empty_bytes.try_reserve_exact(MAX_USIZE) { + if let Err(AllocError { .. }) = empty_bytes.try_reserve_exact(MAX_USIZE) { } else { panic!("usize::MAX should trigger an OOM!") } } } @@ -1231,7 +1231,7 @@ fn test_try_reserve_exact() { if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { } else { panic!("isize::MAX + 1 should trigger an overflow!"); } } else { - if let Err(AllocErr) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { + if let Err(AllocError { .. }) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } } if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_USIZE) { @@ -1252,7 +1252,7 @@ fn test_try_reserve_exact() { if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) { } else { panic!("isize::MAX + 1 should trigger an overflow!"); } } else { - if let Err(AllocErr) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) { + if let Err(AllocError { .. }) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } } if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_USIZE - 20) { diff --git a/src/liballoc/tests/vec_deque.rs b/src/liballoc/tests/vec_deque.rs index 1bbcca97b3c..d49b553fc02 100644 --- a/src/liballoc/tests/vec_deque.rs +++ b/src/liballoc/tests/vec_deque.rs @@ -1,6 +1,6 @@ use std::fmt::Debug; use std::collections::{VecDeque, vec_deque::Drain}; -use std::collections::CollectionAllocErr::*; +use std::collections::TryReserveError::*; use std::mem::size_of; use std::{usize, isize}; @@ -1168,7 +1168,7 @@ fn test_try_reserve() { // VecDeque starts with capacity 7, always adds 1 to the capacity // and also rounds the number to next power of 2 so this is the // furthest we can go without triggering CapacityOverflow - if let Err(AllocErr) = empty_bytes.try_reserve(MAX_CAP) { + if let Err(AllocError { .. }) = empty_bytes.try_reserve(MAX_CAP) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } } } @@ -1188,7 +1188,7 @@ fn test_try_reserve() { if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 9) { } else { panic!("isize::MAX + 1 should trigger an overflow!"); } } else { - if let Err(AllocErr) = ten_bytes.try_reserve(MAX_CAP - 9) { + if let Err(AllocError { .. }) = ten_bytes.try_reserve(MAX_CAP - 9) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } } // Should always overflow in the add-to-len @@ -1211,7 +1211,7 @@ fn test_try_reserve() { if let Err(CapacityOverflow) = ten_u32s.try_reserve(MAX_CAP/4 - 9) { } else { panic!("isize::MAX + 1 should trigger an overflow!"); } } else { - if let Err(AllocErr) = ten_u32s.try_reserve(MAX_CAP/4 - 9) { + if let Err(AllocError { .. }) = ten_u32s.try_reserve(MAX_CAP/4 - 9) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } } // Should fail in the mul-by-size @@ -1256,7 +1256,7 @@ fn test_try_reserve_exact() { // VecDeque starts with capacity 7, always adds 1 to the capacity // and also rounds the number to next power of 2 so this is the // furthest we can go without triggering CapacityOverflow - if let Err(AllocErr) = empty_bytes.try_reserve_exact(MAX_CAP) { + if let Err(AllocError { .. }) = empty_bytes.try_reserve_exact(MAX_CAP) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } } } @@ -1275,7 +1275,7 @@ fn test_try_reserve_exact() { if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { } else { panic!("isize::MAX + 1 should trigger an overflow!"); } } else { - if let Err(AllocErr) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { + if let Err(AllocError { .. }) = ten_bytes.try_reserve_exact(MAX_CAP - 9) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } } if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_USIZE) { @@ -1296,7 +1296,7 @@ fn test_try_reserve_exact() { if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) { } else { panic!("isize::MAX + 1 should trigger an overflow!"); } } else { - if let Err(AllocErr) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) { + if let Err(AllocError { .. }) = ten_u32s.try_reserve_exact(MAX_CAP/4 - 9) { } else { panic!("isize::MAX + 1 should trigger an OOM!") } } if let Err(CapacityOverflow) = ten_u32s.try_reserve_exact(MAX_USIZE - 20) { diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index dac04e4e624..d2798955c46 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -70,7 +70,7 @@ use core::ptr::{self, NonNull}; use core::slice::{self, SliceIndex}; use crate::borrow::{ToOwned, Cow}; -use crate::collections::CollectionAllocErr; +use crate::collections::TryReserveError; use crate::boxed::Box; use crate::raw_vec::RawVec; @@ -498,9 +498,9 @@ impl<T> Vec<T> { /// /// ``` /// #![feature(try_reserve)] - /// use std::collections::CollectionAllocErr; + /// use std::collections::TryReserveError; /// - /// fn process_data(data: &[u32]) -> Result<Vec<u32>, CollectionAllocErr> { + /// fn process_data(data: &[u32]) -> Result<Vec<u32>, TryReserveError> { /// let mut output = Vec::new(); /// /// // Pre-reserve the memory, exiting if we can't @@ -516,7 +516,7 @@ impl<T> Vec<T> { /// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?"); /// ``` #[unstable(feature = "try_reserve", reason = "new API", issue="48043")] - pub fn try_reserve(&mut self, additional: usize) -> Result<(), CollectionAllocErr> { + pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { self.buf.try_reserve(self.len, additional) } @@ -538,9 +538,9 @@ impl<T> Vec<T> { /// /// ``` /// #![feature(try_reserve)] - /// use std::collections::CollectionAllocErr; + /// use std::collections::TryReserveError; /// - /// fn process_data(data: &[u32]) -> Result<Vec<u32>, CollectionAllocErr> { + /// fn process_data(data: &[u32]) -> Result<Vec<u32>, TryReserveError> { /// let mut output = Vec::new(); /// /// // Pre-reserve the memory, exiting if we can't @@ -556,7 +556,7 @@ impl<T> Vec<T> { /// # process_data(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?"); /// ``` #[unstable(feature = "try_reserve", reason = "new API", issue="48043")] - pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), CollectionAllocErr> { + pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { self.buf.try_reserve_exact(self.len, additional) } diff --git a/src/libcore/any.rs b/src/libcore/any.rs index 078091a9b54..e8a0a88f12a 100644 --- a/src/libcore/any.rs +++ b/src/libcore/any.rs @@ -470,10 +470,5 @@ impl TypeId { #[stable(feature = "type_name", since = "1.38.0")] #[rustc_const_unstable(feature = "const_type_name")] pub const fn type_name<T: ?Sized>() -> &'static str { - #[cfg(bootstrap)] - unsafe { - intrinsics::type_name::<T>() - } - #[cfg(not(bootstrap))] intrinsics::type_name::<T>() } diff --git a/src/libcore/ascii.rs b/src/libcore/ascii.rs index e6a6fdde540..4087333e2cf 100644 --- a/src/libcore/ascii.rs +++ b/src/libcore/ascii.rs @@ -14,6 +14,7 @@ use crate::fmt; use crate::ops::Range; use crate::iter::FusedIterator; +use crate::str::from_utf8_unchecked; /// An iterator over the escaped version of a byte. /// @@ -22,6 +23,7 @@ use crate::iter::FusedIterator; /// /// [`escape_default`]: fn.escape_default.html #[stable(feature = "rust1", since = "1.0.0")] +#[derive(Clone)] pub struct EscapeDefault { range: Range<usize>, data: [u8; 4], @@ -130,6 +132,13 @@ impl ExactSizeIterator for EscapeDefault {} #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for EscapeDefault {} +#[stable(feature = "ascii_escape_display", since = "1.39.0")] +impl fmt::Display for EscapeDefault { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(unsafe { from_utf8_unchecked(&self.data[self.range.clone()]) }) + } +} + #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for EscapeDefault { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/src/libcore/char/methods.rs b/src/libcore/char/methods.rs index aa834db2b9b..e91bf53c5b4 100644 --- a/src/libcore/char/methods.rs +++ b/src/libcore/char/methods.rs @@ -553,12 +553,7 @@ impl char { /// `XID_Start` is a Unicode Derived Property specified in /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications), /// mostly similar to `ID_Start` but modified for closure under `NFKx`. - #[cfg_attr(bootstrap, - unstable(feature = "rustc_private", - reason = "mainly needed for compiler internals", - issue = "27812"))] - #[cfg_attr(not(bootstrap), - unstable(feature = "unicode_internals", issue = "0"))] + #[unstable(feature = "unicode_internals", issue = "0")] pub fn is_xid_start(self) -> bool { derived_property::XID_Start(self) } @@ -569,12 +564,7 @@ impl char { /// `XID_Continue` is a Unicode Derived Property specified in /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications), /// mostly similar to `ID_Continue` but modified for closure under NFKx. - #[cfg_attr(bootstrap, - unstable(feature = "rustc_private", - reason = "mainly needed for compiler internals", - issue = "27812"))] - #[cfg_attr(not(bootstrap), - unstable(feature = "unicode_internals", issue = "0"))] + #[unstable(feature = "unicode_internals", issue = "0")] #[inline] pub fn is_xid_continue(self) -> bool { derived_property::XID_Continue(self) diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs index 0c99356390b..ec70d396e96 100644 --- a/src/libcore/clone.rs +++ b/src/libcore/clone.rs @@ -134,9 +134,8 @@ pub trait Clone : Sized { } /// Derive macro generating an impl of the trait `Clone`. -#[cfg(not(bootstrap))] #[rustc_builtin_macro] -#[rustc_macro_transparency = "semitransparent"] +#[cfg_attr(boostrap_stdarch_ignore_this, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics, derive_clone_copy)] pub macro Clone($item:item) { /* compiler built-in */ } diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 38a52d97da2..cb9feb074dd 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -201,9 +201,8 @@ pub trait PartialEq<Rhs: ?Sized = Self> { } /// Derive macro generating an impl of the trait `PartialEq`. -#[cfg(not(bootstrap))] #[rustc_builtin_macro] -#[rustc_macro_transparency = "semitransparent"] +#[cfg_attr(boostrap_stdarch_ignore_this, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics)] pub macro PartialEq($item:item) { /* compiler built-in */ } @@ -265,9 +264,8 @@ pub trait Eq: PartialEq<Self> { } /// Derive macro generating an impl of the trait `Eq`. -#[cfg(not(bootstrap))] #[rustc_builtin_macro] -#[rustc_macro_transparency = "semitransparent"] +#[cfg_attr(boostrap_stdarch_ignore_this, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics, derive_eq)] pub macro Eq($item:item) { /* compiler built-in */ } @@ -617,9 +615,8 @@ pub trait Ord: Eq + PartialOrd<Self> { } /// Derive macro generating an impl of the trait `Ord`. -#[cfg(not(bootstrap))] #[rustc_builtin_macro] -#[rustc_macro_transparency = "semitransparent"] +#[cfg_attr(boostrap_stdarch_ignore_this, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics)] pub macro Ord($item:item) { /* compiler built-in */ } @@ -867,9 +864,8 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> { } /// Derive macro generating an impl of the trait `PartialOrd`. -#[cfg(not(bootstrap))] #[rustc_builtin_macro] -#[rustc_macro_transparency = "semitransparent"] +#[cfg_attr(boostrap_stdarch_ignore_this, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics)] pub macro PartialOrd($item:item) { /* compiler built-in */ } diff --git a/src/libcore/default.rs b/src/libcore/default.rs index 8d95e9de158..66acc5165fc 100644 --- a/src/libcore/default.rs +++ b/src/libcore/default.rs @@ -116,9 +116,8 @@ pub trait Default: Sized { } /// Derive macro generating an impl of the trait `Default`. -#[cfg(not(bootstrap))] #[rustc_builtin_macro] -#[rustc_macro_transparency = "semitransparent"] +#[cfg_attr(boostrap_stdarch_ignore_this, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics)] pub macro Default($item:item) { /* compiler built-in */ } diff --git a/src/libcore/fmt/builders.rs b/src/libcore/fmt/builders.rs index cb4e32622ff..15ce2277fa0 100644 --- a/src/libcore/fmt/builders.rs +++ b/src/libcore/fmt/builders.rs @@ -98,7 +98,7 @@ pub struct DebugStruct<'a, 'b: 'a> { has_fields: bool, } -pub fn debug_struct_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>, +pub(super) fn debug_struct_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>, name: &str) -> DebugStruct<'a, 'b> { let result = fmt.write_str(name); @@ -251,7 +251,10 @@ pub struct DebugTuple<'a, 'b: 'a> { empty_name: bool, } -pub fn debug_tuple_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>, name: &str) -> DebugTuple<'a, 'b> { +pub(super) fn debug_tuple_new<'a, 'b>( + fmt: &'a mut fmt::Formatter<'b>, + name: &str, +) -> DebugTuple<'a, 'b> { let result = fmt.write_str(name); DebugTuple { fmt, @@ -418,7 +421,7 @@ pub struct DebugSet<'a, 'b: 'a> { inner: DebugInner<'a, 'b>, } -pub fn debug_set_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugSet<'a, 'b> { +pub(super) fn debug_set_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugSet<'a, 'b> { let result = fmt.write_str("{"); DebugSet { inner: DebugInner { @@ -555,7 +558,7 @@ pub struct DebugList<'a, 'b: 'a> { inner: DebugInner<'a, 'b>, } -pub fn debug_list_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugList<'a, 'b> { +pub(super) fn debug_list_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugList<'a, 'b> { let result = fmt.write_str("["); DebugList { inner: DebugInner { @@ -697,7 +700,7 @@ pub struct DebugMap<'a, 'b: 'a> { state: PadAdapterState, } -pub fn debug_map_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugMap<'a, 'b> { +pub(super) fn debug_map_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugMap<'a, 'b> { let result = fmt.write_str("{"); DebugMap { fmt, diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 0ea01d4b84a..bd31d25dd03 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -546,16 +546,14 @@ pub trait Debug { } // Separate module to reexport the macro `Debug` from prelude without the trait `Debug`. -#[cfg(not(bootstrap))] pub(crate) mod macros { /// Derive macro generating an impl of the trait `Debug`. #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] + #[cfg_attr(boostrap_stdarch_ignore_this, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics)] pub macro Debug($item:item) { /* compiler built-in */ } } -#[cfg(not(bootstrap))] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[doc(inline)] pub use macros::Debug; diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs index c4cbf40a93a..bf3daa32840 100644 --- a/src/libcore/hash/mod.rs +++ b/src/libcore/hash/mod.rs @@ -199,16 +199,14 @@ pub trait Hash { } // Separate module to reexport the macro `Hash` from prelude without the trait `Hash`. -#[cfg(not(bootstrap))] pub(crate) mod macros { /// Derive macro generating an impl of the trait `Hash`. #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] + #[cfg_attr(boostrap_stdarch_ignore_this, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics)] pub macro Hash($item:item) { /* compiler built-in */ } } -#[cfg(not(bootstrap))] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[doc(inline)] pub use macros::Hash; @@ -553,8 +551,6 @@ impl<H> PartialEq for BuildHasherDefault<H> { #[stable(since = "1.29.0", feature = "build_hasher_eq")] impl<H> Eq for BuildHasherDefault<H> {} -////////////////////////////////////////////////////////////////////////////// - mod impls { use crate::mem; use crate::slice; diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index ceaa870d2b3..d145f2212f9 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -1293,18 +1293,40 @@ extern "rust-intrinsic" { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `wrapping_add` method. For example, /// [`std::u32::wrapping_add`](../../std/primitive.u32.html#method.wrapping_add) + #[cfg(boostrap_stdarch_ignore_this)] pub fn overflowing_add<T>(a: T, b: T) -> T; /// Returns (a - b) mod 2<sup>N</sup>, where N is the width of T in bits. /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `wrapping_sub` method. For example, /// [`std::u32::wrapping_sub`](../../std/primitive.u32.html#method.wrapping_sub) + #[cfg(boostrap_stdarch_ignore_this)] pub fn overflowing_sub<T>(a: T, b: T) -> T; /// Returns (a * b) mod 2<sup>N</sup>, where N is the width of T in bits. /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `wrapping_mul` method. For example, /// [`std::u32::wrapping_mul`](../../std/primitive.u32.html#method.wrapping_mul) + #[cfg(boostrap_stdarch_ignore_this)] pub fn overflowing_mul<T>(a: T, b: T) -> T; + /// Returns (a + b) mod 2<sup>N</sup>, where N is the width of T in bits. + /// The stabilized versions of this intrinsic are available on the integer + /// primitives via the `wrapping_add` method. For example, + /// [`std::u32::wrapping_add`](../../std/primitive.u32.html#method.wrapping_add) + #[cfg(not(boostrap_stdarch_ignore_this))] + pub fn wrapping_add<T>(a: T, b: T) -> T; + /// Returns (a - b) mod 2<sup>N</sup>, where N is the width of T in bits. + /// The stabilized versions of this intrinsic are available on the integer + /// primitives via the `wrapping_sub` method. For example, + /// [`std::u32::wrapping_sub`](../../std/primitive.u32.html#method.wrapping_sub) + #[cfg(not(boostrap_stdarch_ignore_this))] + pub fn wrapping_sub<T>(a: T, b: T) -> T; + /// Returns (a * b) mod 2<sup>N</sup>, where N is the width of T in bits. + /// The stabilized versions of this intrinsic are available on the integer + /// primitives via the `wrapping_mul` method. For example, + /// [`std::u32::wrapping_mul`](../../std/primitive.u32.html#method.wrapping_mul) + #[cfg(not(boostrap_stdarch_ignore_this))] + pub fn wrapping_mul<T>(a: T, b: T) -> T; + /// Computes `a + b`, while saturating at numeric bounds. /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `saturating_add` method. For example, diff --git a/src/libcore/iter/adapters/chain.rs b/src/libcore/iter/adapters/chain.rs index 76239ebc0ab..c9612596b1b 100644 --- a/src/libcore/iter/adapters/chain.rs +++ b/src/libcore/iter/adapters/chain.rs @@ -173,17 +173,23 @@ impl<A, B> Iterator for Chain<A, B> where #[inline] fn size_hint(&self) -> (usize, Option<usize>) { - let (a_lower, a_upper) = self.a.size_hint(); - let (b_lower, b_upper) = self.b.size_hint(); + match self.state { + ChainState::Both => { + let (a_lower, a_upper) = self.a.size_hint(); + let (b_lower, b_upper) = self.b.size_hint(); - let lower = a_lower.saturating_add(b_lower); + let lower = a_lower.saturating_add(b_lower); - let upper = match (a_upper, b_upper) { - (Some(x), Some(y)) => x.checked_add(y), - _ => None - }; + let upper = match (a_upper, b_upper) { + (Some(x), Some(y)) => x.checked_add(y), + _ => None + }; - (lower, upper) + (lower, upper) + } + ChainState::Front => self.a.size_hint(), + ChainState::Back => self.b.size_hint(), + } } } @@ -207,6 +213,29 @@ impl<A, B> DoubleEndedIterator for Chain<A, B> where } } + #[inline] + fn nth_back(&mut self, mut n: usize) -> Option<A::Item> { + match self.state { + ChainState::Both | ChainState::Back => { + for x in self.b.by_ref().rev() { + if n == 0 { + return Some(x) + } + n -= 1; + } + if let ChainState::Both = self.state { + self.state = ChainState::Front; + } + } + ChainState::Front => {} + } + if let ChainState::Front = self.state { + self.a.nth_back(n) + } else { + None + } + } + fn try_rfold<Acc, F, R>(&mut self, init: Acc, mut f: F) -> R where Self: Sized, F: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> { diff --git a/src/libcore/iter/adapters/flatten.rs b/src/libcore/iter/adapters/flatten.rs index d8d41a2a31e..a45173f614d 100644 --- a/src/libcore/iter/adapters/flatten.rs +++ b/src/libcore/iter/adapters/flatten.rs @@ -72,8 +72,7 @@ impl<I: Iterator, U: IntoIterator, F> Iterator for FlatMap<I, U, F> impl<I: DoubleEndedIterator, U, F> DoubleEndedIterator for FlatMap<I, U, F> where F: FnMut(I::Item) -> U, - U: IntoIterator, - U::IntoIter: DoubleEndedIterator, + U: IntoIterator<IntoIter: DoubleEndedIterator>, { #[inline] fn next_back(&mut self) -> Option<U::Item> { self.inner.next_back() } @@ -107,10 +106,7 @@ impl<I, U, F> FusedIterator for FlatMap<I, U, F> /// [`Iterator`]: trait.Iterator.html #[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "iterator_flatten", since = "1.29.0")] -pub struct Flatten<I: Iterator> -where - I::Item: IntoIterator, -{ +pub struct Flatten<I: Iterator<Item: IntoIterator>> { inner: FlattenCompat<I, <I::Item as IntoIterator>::IntoIter>, } @@ -229,7 +225,7 @@ where if let elt@Some(_) = inner.next() { return elt } } match self.iter.next() { - None => return self.backiter.as_mut().and_then(|it| it.next()), + None => return self.backiter.as_mut()?.next(), Some(inner) => self.frontiter = Some(inner.into_iter()), } } @@ -237,8 +233,8 @@ where #[inline] fn size_hint(&self) -> (usize, Option<usize>) { - let (flo, fhi) = self.frontiter.as_ref().map_or((0, Some(0)), |it| it.size_hint()); - let (blo, bhi) = self.backiter.as_ref().map_or((0, Some(0)), |it| it.size_hint()); + let (flo, fhi) = self.frontiter.as_ref().map_or((0, Some(0)), U::size_hint); + let (blo, bhi) = self.backiter.as_ref().map_or((0, Some(0)), U::size_hint); let lo = flo.saturating_add(blo); match (self.iter.size_hint(), fhi, bhi) { ((0, Some(0)), Some(a), Some(b)) => (lo, a.checked_add(b)), @@ -250,20 +246,25 @@ where fn try_fold<Acc, Fold, R>(&mut self, mut init: Acc, mut fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> { + #[inline] + fn flatten<'a, T: IntoIterator, Acc, R: Try<Ok = Acc>>( + frontiter: &'a mut Option<T::IntoIter>, + fold: &'a mut impl FnMut(Acc, T::Item) -> R, + ) -> impl FnMut(Acc, T) -> R + 'a { + move |acc, x| { + let mut mid = x.into_iter(); + let r = mid.try_fold(acc, &mut *fold); + *frontiter = Some(mid); + r + } + } + if let Some(ref mut front) = self.frontiter { init = front.try_fold(init, &mut fold)?; } self.frontiter = None; - { - let frontiter = &mut self.frontiter; - init = self.iter.try_fold(init, |acc, x| { - let mut mid = x.into_iter(); - let r = mid.try_fold(acc, &mut fold); - *frontiter = Some(mid); - r - })?; - } + init = self.iter.try_fold(init, flatten(&mut self.frontiter, &mut fold))?; self.frontiter = None; if let Some(ref mut back) = self.backiter { @@ -275,13 +276,20 @@ where } #[inline] - fn fold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc + fn fold<Acc, Fold>(self, init: Acc, ref mut fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { + #[inline] + fn flatten<U: Iterator, Acc>( + fold: &mut impl FnMut(Acc, U::Item) -> Acc, + ) -> impl FnMut(Acc, U) -> Acc + '_ { + move |acc, iter| iter.fold(acc, &mut *fold) + } + self.frontiter.into_iter() .chain(self.iter.map(IntoIterator::into_iter)) .chain(self.backiter) - .fold(init, |acc, iter| iter.fold(acc, &mut fold)) + .fold(init, flatten(fold)) } } @@ -297,7 +305,7 @@ where if let elt@Some(_) = inner.next_back() { return elt } } match self.iter.next_back() { - None => return self.frontiter.as_mut().and_then(|it| it.next_back()), + None => return self.frontiter.as_mut()?.next_back(), next => self.backiter = next.map(IntoIterator::into_iter), } } @@ -307,22 +315,29 @@ where fn try_rfold<Acc, Fold, R>(&mut self, mut init: Acc, mut fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> { - if let Some(ref mut back) = self.backiter { - init = back.try_rfold(init, &mut fold)?; - } - self.backiter = None; - + #[inline] + fn flatten<'a, T: IntoIterator, Acc, R: Try<Ok = Acc>>( + backiter: &'a mut Option<T::IntoIter>, + fold: &'a mut impl FnMut(Acc, T::Item) -> R, + ) -> impl FnMut(Acc, T) -> R + 'a where + T::IntoIter: DoubleEndedIterator, { - let backiter = &mut self.backiter; - init = self.iter.try_rfold(init, |acc, x| { + move |acc, x| { let mut mid = x.into_iter(); - let r = mid.try_rfold(acc, &mut fold); + let r = mid.try_rfold(acc, &mut *fold); *backiter = Some(mid); r - })?; + } + } + + if let Some(ref mut back) = self.backiter { + init = back.try_rfold(init, &mut fold)?; } self.backiter = None; + init = self.iter.try_rfold(init, flatten(&mut self.backiter, &mut fold))?; + self.backiter = None; + if let Some(ref mut front) = self.frontiter { init = front.try_rfold(init, &mut fold)?; } @@ -332,12 +347,19 @@ where } #[inline] - fn rfold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc + fn rfold<Acc, Fold>(self, init: Acc, ref mut fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { + #[inline] + fn flatten<U: DoubleEndedIterator, Acc>( + fold: &mut impl FnMut(Acc, U::Item) -> Acc, + ) -> impl FnMut(Acc, U) -> Acc + '_ { + move |acc, iter| iter.rfold(acc, &mut *fold) + } + self.frontiter.into_iter() .chain(self.iter.map(IntoIterator::into_iter)) .chain(self.backiter) - .rfold(init, |acc, iter| iter.rfold(acc, &mut fold)) + .rfold(init, flatten(fold)) } } diff --git a/src/libcore/iter/adapters/mod.rs b/src/libcore/iter/adapters/mod.rs index b2702902956..a63434abd6c 100644 --- a/src/libcore/iter/adapters/mod.rs +++ b/src/libcore/iter/adapters/mod.rs @@ -1,6 +1,6 @@ use crate::cmp; use crate::fmt; -use crate::ops::Try; +use crate::ops::{Add, AddAssign, Try}; use crate::usize; use crate::intrinsics; @@ -143,6 +143,18 @@ impl<I> Copied<I> { } } +fn copy_fold<T: Copy, Acc>( + mut f: impl FnMut(Acc, T) -> Acc, +) -> impl FnMut(Acc, &T) -> Acc { + move |acc, &elt| f(acc, elt) +} + +fn copy_try_fold<T: Copy, Acc, R>( + mut f: impl FnMut(Acc, T) -> R, +) -> impl FnMut(Acc, &T) -> R { + move |acc, &elt| f(acc, elt) +} + #[stable(feature = "iter_copied", since = "1.36.0")] impl<'a, I, T: 'a> Iterator for Copied<I> where I: Iterator<Item=&'a T>, T: Copy @@ -157,16 +169,16 @@ impl<'a, I, T: 'a> Iterator for Copied<I> self.it.size_hint() } - fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R where + fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R where Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Ok=B> { - self.it.try_fold(init, move |acc, &elt| f(acc, elt)) + self.it.try_fold(init, copy_try_fold(f)) } - fn fold<Acc, F>(self, init: Acc, mut f: F) -> Acc + fn fold<Acc, F>(self, init: Acc, f: F) -> Acc where F: FnMut(Acc, Self::Item) -> Acc, { - self.it.fold(init, move |acc, &elt| f(acc, elt)) + self.it.fold(init, copy_fold(f)) } } @@ -178,16 +190,16 @@ impl<'a, I, T: 'a> DoubleEndedIterator for Copied<I> self.it.next_back().copied() } - fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R where + fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R where Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Ok=B> { - self.it.try_rfold(init, move |acc, &elt| f(acc, elt)) + self.it.try_rfold(init, copy_try_fold(f)) } - fn rfold<Acc, F>(self, init: Acc, mut f: F) -> Acc + fn rfold<Acc, F>(self, init: Acc, f: F) -> Acc where F: FnMut(Acc, Self::Item) -> Acc, { - self.it.rfold(init, move |acc, &elt| f(acc, elt)) + self.it.rfold(init, copy_fold(f)) } } @@ -248,6 +260,12 @@ impl<I> Cloned<I> { } } +fn clone_try_fold<T: Clone, Acc, R>( + mut f: impl FnMut(Acc, T) -> R, +) -> impl FnMut(Acc, &T) -> R { + move |acc, elt| f(acc, elt.clone()) +} + #[stable(feature = "iter_cloned", since = "1.1.0")] impl<'a, I, T: 'a> Iterator for Cloned<I> where I: Iterator<Item=&'a T>, T: Clone @@ -262,16 +280,16 @@ impl<'a, I, T: 'a> Iterator for Cloned<I> self.it.size_hint() } - fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R where + fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R where Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Ok=B> { - self.it.try_fold(init, move |acc, elt| f(acc, elt.clone())) + self.it.try_fold(init, clone_try_fold(f)) } - fn fold<Acc, F>(self, init: Acc, mut f: F) -> Acc + fn fold<Acc, F>(self, init: Acc, f: F) -> Acc where F: FnMut(Acc, Self::Item) -> Acc, { - self.it.fold(init, move |acc, elt| f(acc, elt.clone())) + self.it.map(T::clone).fold(init, f) } } @@ -283,16 +301,16 @@ impl<'a, I, T: 'a> DoubleEndedIterator for Cloned<I> self.it.next_back().cloned() } - fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R where + fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R where Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Ok=B> { - self.it.try_rfold(init, move |acc, elt| f(acc, elt.clone())) + self.it.try_rfold(init, clone_try_fold(f)) } - fn rfold<Acc, F>(self, init: Acc, mut f: F) -> Acc + fn rfold<Acc, F>(self, init: Acc, f: F) -> Acc where F: FnMut(Acc, Self::Item) -> Acc, { - self.it.rfold(init, move |acc, elt| f(acc, elt.clone())) + self.it.map(T::clone).rfold(init, f) } } @@ -387,6 +405,36 @@ impl<I> Iterator for Cycle<I> where I: Clone + Iterator { _ => (usize::MAX, None) } } + + #[inline] + fn try_fold<Acc, F, R>(&mut self, mut acc: Acc, mut f: F) -> R + where + F: FnMut(Acc, Self::Item) -> R, + R: Try<Ok = Acc>, + { + // fully iterate the current iterator. this is necessary because + // `self.iter` may be empty even when `self.orig` isn't + acc = self.iter.try_fold(acc, &mut f)?; + self.iter = self.orig.clone(); + + // complete a full cycle, keeping track of whether the cycled + // iterator is empty or not. we need to return early in case + // of an empty iterator to prevent an infinite loop + let mut is_empty = true; + acc = self.iter.try_fold(acc, |acc, x| { + is_empty = false; + f(acc, x) + })?; + + if is_empty { + return Try::from_ok(acc); + } + + loop { + self.iter = self.orig.clone(); + acc = self.iter.try_fold(acc, &mut f)?; + } + } } #[stable(feature = "fused", since = "1.26.0")] @@ -430,14 +478,24 @@ impl<I> Iterator for StepBy<I> where I: Iterator { #[inline] fn size_hint(&self) -> (usize, Option<usize>) { - let inner_hint = self.iter.size_hint(); + #[inline] + fn first_size(step: usize) -> impl Fn(usize) -> usize { + move |n| if n == 0 { 0 } else { 1 + (n - 1) / (step + 1) } + } + + #[inline] + fn other_size(step: usize) -> impl Fn(usize) -> usize { + move |n| n / (step + 1) + } + + let (low, high) = self.iter.size_hint(); if self.first_take { - let f = |n| if n == 0 { 0 } else { 1 + (n-1)/(self.step+1) }; - (f(inner_hint.0), inner_hint.1.map(f)) + let f = first_size(self.step); + (f(low), high.map(f)) } else { - let f = |n| n / (self.step+1); - (f(inner_hint.0), inner_hint.1.map(f)) + let f = other_size(self.step); + (f(low), high.map(f)) } } @@ -594,6 +652,20 @@ impl<I: fmt::Debug, F> fmt::Debug for Map<I, F> { } } +fn map_fold<T, B, Acc>( + mut f: impl FnMut(T) -> B, + mut g: impl FnMut(Acc, B) -> Acc, +) -> impl FnMut(Acc, T) -> Acc { + move |acc, elt| g(acc, f(elt)) +} + +fn map_try_fold<'a, T, B, Acc, R>( + f: &'a mut impl FnMut(T) -> B, + mut g: impl FnMut(Acc, B) -> R + 'a, +) -> impl FnMut(Acc, T) -> R + 'a { + move |acc, elt| g(acc, f(elt)) +} + #[stable(feature = "rust1", since = "1.0.0")] impl<B, I: Iterator, F> Iterator for Map<I, F> where F: FnMut(I::Item) -> B { type Item = B; @@ -608,18 +680,16 @@ impl<B, I: Iterator, F> Iterator for Map<I, F> where F: FnMut(I::Item) -> B { self.iter.size_hint() } - fn try_fold<Acc, G, R>(&mut self, init: Acc, mut g: G) -> R where + fn try_fold<Acc, G, R>(&mut self, init: Acc, g: G) -> R where Self: Sized, G: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> { - let f = &mut self.f; - self.iter.try_fold(init, move |acc, elt| g(acc, f(elt))) + self.iter.try_fold(init, map_try_fold(&mut self.f, g)) } - fn fold<Acc, G>(self, init: Acc, mut g: G) -> Acc + fn fold<Acc, G>(self, init: Acc, g: G) -> Acc where G: FnMut(Acc, Self::Item) -> Acc, { - let mut f = self.f; - self.iter.fold(init, move |acc, elt| g(acc, f(elt))) + self.iter.fold(init, map_fold(self.f, g)) } } @@ -632,18 +702,16 @@ impl<B, I: DoubleEndedIterator, F> DoubleEndedIterator for Map<I, F> where self.iter.next_back().map(&mut self.f) } - fn try_rfold<Acc, G, R>(&mut self, init: Acc, mut g: G) -> R where + fn try_rfold<Acc, G, R>(&mut self, init: Acc, g: G) -> R where Self: Sized, G: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> { - let f = &mut self.f; - self.iter.try_rfold(init, move |acc, elt| g(acc, f(elt))) + self.iter.try_rfold(init, map_try_fold(&mut self.f, g)) } - fn rfold<Acc, G>(self, init: Acc, mut g: G) -> Acc + fn rfold<Acc, G>(self, init: Acc, g: G) -> Acc where G: FnMut(Acc, Self::Item) -> Acc, { - let mut f = self.f; - self.iter.rfold(init, move |acc, elt| g(acc, f(elt))) + self.iter.rfold(init, map_fold(self.f, g)) } } @@ -710,13 +778,27 @@ impl<I: fmt::Debug, P> fmt::Debug for Filter<I, P> { } } +fn filter_fold<T, Acc>( + mut predicate: impl FnMut(&T) -> bool, + mut fold: impl FnMut(Acc, T) -> Acc, +) -> impl FnMut(Acc, T) -> Acc { + move |acc, item| if predicate(&item) { fold(acc, item) } else { acc } +} + +fn filter_try_fold<'a, T, Acc, R: Try<Ok = Acc>>( + predicate: &'a mut impl FnMut(&T) -> bool, + mut fold: impl FnMut(Acc, T) -> R + 'a, +) -> impl FnMut(Acc, T) -> R + 'a { + move |acc, item| if predicate(&item) { fold(acc, item) } else { R::from_ok(acc) } +} + #[stable(feature = "rust1", since = "1.0.0")] impl<I: Iterator, P> Iterator for Filter<I, P> where P: FnMut(&I::Item) -> bool { type Item = I::Item; #[inline] fn next(&mut self) -> Option<I::Item> { - self.try_for_each(Err).err() + self.iter.find(&mut self.predicate) } #[inline] @@ -738,32 +820,26 @@ impl<I: Iterator, P> Iterator for Filter<I, P> where P: FnMut(&I::Item) -> bool // leaving more budget for LLVM optimizations. #[inline] fn count(self) -> usize { - let mut predicate = self.predicate; - self.iter.map(|x| predicate(&x) as usize).sum() + #[inline] + fn to_usize<T>(mut predicate: impl FnMut(&T) -> bool) -> impl FnMut(T) -> usize { + move |x| predicate(&x) as usize + } + + self.iter.map(to_usize(self.predicate)).sum() } #[inline] - fn try_fold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where + fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> { - let predicate = &mut self.predicate; - self.iter.try_fold(init, move |acc, item| if predicate(&item) { - fold(acc, item) - } else { - Try::from_ok(acc) - }) + self.iter.try_fold(init, filter_try_fold(&mut self.predicate, fold)) } #[inline] - fn fold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc + fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { - let mut predicate = self.predicate; - self.iter.fold(init, move |acc, item| if predicate(&item) { - fold(acc, item) - } else { - acc - }) + self.iter.fold(init, filter_fold(self.predicate, fold)) } } @@ -773,31 +849,21 @@ impl<I: DoubleEndedIterator, P> DoubleEndedIterator for Filter<I, P> { #[inline] fn next_back(&mut self) -> Option<I::Item> { - self.try_rfold((), |_, x| Err(x)).err() + self.iter.rfind(&mut self.predicate) } #[inline] - fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where + fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> { - let predicate = &mut self.predicate; - self.iter.try_rfold(init, move |acc, item| if predicate(&item) { - fold(acc, item) - } else { - Try::from_ok(acc) - }) + self.iter.try_rfold(init, filter_try_fold(&mut self.predicate, fold)) } #[inline] - fn rfold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc + fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { - let mut predicate = self.predicate; - self.iter.rfold(init, move |acc, item| if predicate(&item) { - fold(acc, item) - } else { - acc - }) + self.iter.rfold(init, filter_fold(self.predicate, fold)) } } @@ -834,6 +900,26 @@ impl<I: fmt::Debug, F> fmt::Debug for FilterMap<I, F> { } } +fn filter_map_fold<T, B, Acc>( + mut f: impl FnMut(T) -> Option<B>, + mut fold: impl FnMut(Acc, B) -> Acc, +) -> impl FnMut(Acc, T) -> Acc { + move |acc, item| match f(item) { + Some(x) => fold(acc, x), + None => acc, + } +} + +fn filter_map_try_fold<'a, T, B, Acc, R: Try<Ok = Acc>>( + f: &'a mut impl FnMut(T) -> Option<B>, + mut fold: impl FnMut(Acc, B) -> R + 'a, +) -> impl FnMut(Acc, T) -> R + 'a { + move |acc, item| match f(item) { + Some(x) => fold(acc, x), + None => R::from_ok(acc), + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl<B, I: Iterator, F> Iterator for FilterMap<I, F> where F: FnMut(I::Item) -> Option<B>, @@ -842,7 +928,7 @@ impl<B, I: Iterator, F> Iterator for FilterMap<I, F> #[inline] fn next(&mut self) -> Option<B> { - self.try_for_each(Err).err() + self.iter.find_map(&mut self.f) } #[inline] @@ -852,25 +938,17 @@ impl<B, I: Iterator, F> Iterator for FilterMap<I, F> } #[inline] - fn try_fold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where + fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> { - let f = &mut self.f; - self.iter.try_fold(init, move |acc, item| match f(item) { - Some(x) => fold(acc, x), - None => Try::from_ok(acc), - }) + self.iter.try_fold(init, filter_map_try_fold(&mut self.f, fold)) } #[inline] - fn fold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc + fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { - let mut f = self.f; - self.iter.fold(init, move |acc, item| match f(item) { - Some(x) => fold(acc, x), - None => acc, - }) + self.iter.fold(init, filter_map_fold(self.f, fold)) } } @@ -880,29 +958,31 @@ impl<B, I: DoubleEndedIterator, F> DoubleEndedIterator for FilterMap<I, F> { #[inline] fn next_back(&mut self) -> Option<B> { - self.try_rfold((), |_, x| Err(x)).err() + #[inline] + fn find<T, B>( + f: &mut impl FnMut(T) -> Option<B> + ) -> impl FnMut((), T) -> LoopState<(), B> + '_ { + move |(), x| match f(x) { + Some(x) => LoopState::Break(x), + None => LoopState::Continue(()), + } + } + + self.iter.try_rfold((), find(&mut self.f)).break_value() } #[inline] - fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where + fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> { - let f = &mut self.f; - self.iter.try_rfold(init, move |acc, item| match f(item) { - Some(x) => fold(acc, x), - None => Try::from_ok(acc), - }) + self.iter.try_rfold(init, filter_map_try_fold(&mut self.f, fold)) } #[inline] - fn rfold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc + fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { - let mut f = self.f; - self.iter.rfold(init, move |acc, item| match f(item) { - Some(x) => fold(acc, x), - None => acc, - }) + self.iter.rfold(init, filter_map_fold(self.f, fold)) } } @@ -944,14 +1024,12 @@ impl<I> Iterator for Enumerate<I> where I: Iterator { /// /// Might panic if the index of the element overflows a `usize`. #[inline] - #[rustc_inherit_overflow_checks] fn next(&mut self) -> Option<(usize, <I as Iterator>::Item)> { - self.iter.next().map(|a| { - let ret = (self.count, a); - // Possible undefined overflow. - self.count += 1; - ret - }) + let a = self.iter.next()?; + let i = self.count; + // Possible undefined overflow. + AddAssign::add_assign(&mut self.count, 1); + Some((i, a)) } #[inline] @@ -960,13 +1038,12 @@ impl<I> Iterator for Enumerate<I> where I: Iterator { } #[inline] - #[rustc_inherit_overflow_checks] fn nth(&mut self, n: usize) -> Option<(usize, I::Item)> { - self.iter.nth(n).map(|a| { - let i = self.count + n; - self.count = i + 1; - (i, a) - }) + let a = self.iter.nth(n)?; + // Possible undefined overflow. + let i = Add::add(self.count, n); + self.count = Add::add(i, 1); + Some((i, a)) } #[inline] @@ -975,29 +1052,43 @@ impl<I> Iterator for Enumerate<I> where I: Iterator { } #[inline] - #[rustc_inherit_overflow_checks] - fn try_fold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where + fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> { - let count = &mut self.count; - self.iter.try_fold(init, move |acc, item| { - let acc = fold(acc, (*count, item)); - *count += 1; - acc - }) + #[inline] + fn enumerate<'a, T, Acc, R>( + count: &'a mut usize, + mut fold: impl FnMut(Acc, (usize, T)) -> R + 'a, + ) -> impl FnMut(Acc, T) -> R + 'a { + move |acc, item| { + let acc = fold(acc, (*count, item)); + // Possible undefined overflow. + AddAssign::add_assign(count, 1); + acc + } + } + + self.iter.try_fold(init, enumerate(&mut self.count, fold)) } #[inline] - #[rustc_inherit_overflow_checks] - fn fold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc + fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { - let mut count = self.count; - self.iter.fold(init, move |acc, item| { - let acc = fold(acc, (count, item)); - count += 1; - acc - }) + #[inline] + fn enumerate<T, Acc>( + mut count: usize, + mut fold: impl FnMut(Acc, (usize, T)) -> Acc, + ) -> impl FnMut(Acc, T) -> Acc { + move |acc, item| { + let acc = fold(acc, (count, item)); + // Possible undefined overflow. + AddAssign::add_assign(&mut count, 1); + acc + } + } + + self.iter.fold(init, enumerate(self.count, fold)) } } @@ -1007,48 +1098,60 @@ impl<I> DoubleEndedIterator for Enumerate<I> where { #[inline] fn next_back(&mut self) -> Option<(usize, <I as Iterator>::Item)> { - self.iter.next_back().map(|a| { - let len = self.iter.len(); - // Can safely add, `ExactSizeIterator` promises that the number of - // elements fits into a `usize`. - (self.count + len, a) - }) + let a = self.iter.next_back()?; + let len = self.iter.len(); + // Can safely add, `ExactSizeIterator` promises that the number of + // elements fits into a `usize`. + Some((self.count + len, a)) } #[inline] fn nth_back(&mut self, n: usize) -> Option<(usize, <I as Iterator>::Item)> { - self.iter.nth_back(n).map(|a| { - let len = self.iter.len(); - // Can safely add, `ExactSizeIterator` promises that the number of - // elements fits into a `usize`. - (self.count + len, a) - }) + let a = self.iter.nth_back(n)?; + let len = self.iter.len(); + // Can safely add, `ExactSizeIterator` promises that the number of + // elements fits into a `usize`. + Some((self.count + len, a)) } #[inline] - fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where + fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> { // Can safely add and subtract the count, as `ExactSizeIterator` promises // that the number of elements fits into a `usize`. - let mut count = self.count + self.iter.len(); - self.iter.try_rfold(init, move |acc, item| { - count -= 1; - fold(acc, (count, item)) - }) + fn enumerate<T, Acc, R>( + mut count: usize, + mut fold: impl FnMut(Acc, (usize, T)) -> R, + ) -> impl FnMut(Acc, T) -> R { + move |acc, item| { + count -= 1; + fold(acc, (count, item)) + } + } + + let count = self.count + self.iter.len(); + self.iter.try_rfold(init, enumerate(count, fold)) } #[inline] - fn rfold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc + fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { // Can safely add and subtract the count, as `ExactSizeIterator` promises // that the number of elements fits into a `usize`. - let mut count = self.count + self.iter.len(); - self.iter.rfold(init, move |acc, item| { - count -= 1; - fold(acc, (count, item)) - }) + fn enumerate<T, Acc>( + mut count: usize, + mut fold: impl FnMut(Acc, (usize, T)) -> Acc, + ) -> impl FnMut(Acc, T) -> Acc { + move |acc, item| { + count -= 1; + fold(acc, (count, item)) + } + } + + let count = self.count + self.iter.len(); + self.iter.rfold(init, enumerate(count, fold)) } } @@ -1162,7 +1265,10 @@ impl<I: Iterator> Iterator for Peekable<I> { }; let (lo, hi) = self.iter.size_hint(); let lo = lo.saturating_add(peek_len); - let hi = hi.and_then(|x| x.checked_add(peek_len)); + let hi = match hi { + Some(x) => x.checked_add(peek_len), + None => None, + }; (lo, hi) } @@ -1321,16 +1427,23 @@ impl<I: Iterator, P> Iterator for SkipWhile<I, P> #[inline] fn next(&mut self) -> Option<I::Item> { + fn check<'a, T>( + flag: &'a mut bool, + pred: &'a mut impl FnMut(&T) -> bool, + ) -> impl FnMut(&T) -> bool + 'a { + move |x| { + if *flag || !pred(x) { + *flag = true; + true + } else { + false + } + } + } + let flag = &mut self.flag; let pred = &mut self.predicate; - self.iter.find(move |x| { - if *flag || !pred(x) { - *flag = true; - true - } else { - false - } - }) + self.iter.find(check(flag, pred)) } #[inline] @@ -1412,14 +1525,13 @@ impl<I: Iterator, P> Iterator for TakeWhile<I, P> if self.flag { None } else { - self.iter.next().and_then(|x| { - if (self.predicate)(&x) { - Some(x) - } else { - self.flag = true; - None - } - }) + let x = self.iter.next()?; + if (self.predicate)(&x) { + Some(x) + } else { + self.flag = true; + None + } } } @@ -1434,22 +1546,30 @@ impl<I: Iterator, P> Iterator for TakeWhile<I, P> } #[inline] - fn try_fold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where + fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> { - if self.flag { - Try::from_ok(init) - } else { - let flag = &mut self.flag; - let p = &mut self.predicate; - self.iter.try_fold(init, move |acc, x|{ + fn check<'a, T, Acc, R: Try<Ok = Acc>>( + flag: &'a mut bool, + p: &'a mut impl FnMut(&T) -> bool, + mut fold: impl FnMut(Acc, T) -> R + 'a, + ) -> impl FnMut(Acc, T) -> LoopState<Acc, R> + 'a { + move |acc, x| { if p(&x) { LoopState::from_try(fold(acc, x)) } else { *flag = true; LoopState::Break(Try::from_ok(acc)) } - }).into_try() + } + } + + if self.flag { + Try::from_ok(init) + } else { + let flag = &mut self.flag; + let p = &mut self.predicate; + self.iter.try_fold(init, check(flag, p, fold)).into_try() } } } @@ -1534,7 +1654,10 @@ impl<I> Iterator for Skip<I> where I: Iterator { let (lower, upper) = self.iter.size_hint(); let lower = lower.saturating_sub(self.n); - let upper = upper.map(|x| x.saturating_sub(self.n)); + let upper = match upper { + Some(x) => Some(x.saturating_sub(self.n)), + None => None, + }; (lower, upper) } @@ -1595,19 +1718,26 @@ impl<I> DoubleEndedIterator for Skip<I> where I: DoubleEndedIterator + ExactSize } } - fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where + fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> { - let mut n = self.len(); - if n == 0 { - Try::from_ok(init) - } else { - self.iter.try_rfold(init, move |acc, x| { + fn check<T, Acc, R: Try<Ok = Acc>>( + mut n: usize, + mut fold: impl FnMut(Acc, T) -> R, + ) -> impl FnMut(Acc, T) -> LoopState<Acc, R> { + move |acc, x| { n -= 1; let r = fold(acc, x); if n == 0 { LoopState::Break(r) } else { LoopState::from_try(r) } - }).into_try() + } + } + + let n = self.len(); + if n == 0 { + Try::from_ok(init) + } else { + self.iter.try_rfold(init, check(n, fold)).into_try() } } } @@ -1682,19 +1812,26 @@ impl<I> Iterator for Take<I> where I: Iterator{ } #[inline] - fn try_fold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where + fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> { - if self.n == 0 { - Try::from_ok(init) - } else { - let n = &mut self.n; - self.iter.try_fold(init, move |acc, x| { + fn check<'a, T, Acc, R: Try<Ok = Acc>>( + n: &'a mut usize, + mut fold: impl FnMut(Acc, T) -> R + 'a, + ) -> impl FnMut(Acc, T) -> LoopState<Acc, R> + 'a { + move |acc, x| { *n -= 1; let r = fold(acc, x); if *n == 0 { LoopState::Break(r) } else { LoopState::from_try(r) } - }).into_try() + } + } + + if self.n == 0 { + Try::from_ok(init) + } else { + let n = &mut self.n; + self.iter.try_fold(init, check(n, fold)).into_try() } } } @@ -1793,7 +1930,8 @@ impl<B, I, St, F> Iterator for Scan<I, St, F> where #[inline] fn next(&mut self) -> Option<B> { - self.iter.next().and_then(|a| (self.f)(&mut self.state, a)) + let a = self.iter.next()?; + (self.f)(&mut self.state, a) } #[inline] @@ -1803,17 +1941,25 @@ impl<B, I, St, F> Iterator for Scan<I, St, F> where } #[inline] - fn try_fold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where + fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> { + fn scan<'a, T, St, B, Acc, R: Try<Ok = Acc>>( + state: &'a mut St, + f: &'a mut impl FnMut(&mut St, T) -> Option<B>, + mut fold: impl FnMut(Acc, B) -> R + 'a, + ) -> impl FnMut(Acc, T) -> LoopState<Acc, R> + 'a { + move |acc, x| { + match f(state, x) { + None => LoopState::Break(Try::from_ok(acc)), + Some(x) => LoopState::from_try(fold(acc, x)), + } + } + } + let state = &mut self.state; let f = &mut self.f; - self.iter.try_fold(init, move |acc, x| { - match f(state, x) { - None => LoopState::Break(Try::from_ok(acc)), - Some(x) => LoopState::from_try(fold(acc, x)), - } - }).into_try() + self.iter.try_fold(init, scan(state, f, fold)).into_try() } } @@ -2104,6 +2250,20 @@ impl<I: Iterator, F> Inspect<I, F> where F: FnMut(&I::Item) { } } +fn inspect_fold<T, Acc>( + mut f: impl FnMut(&T), + mut fold: impl FnMut(Acc, T) -> Acc, +) -> impl FnMut(Acc, T) -> Acc { + move |acc, item| { f(&item); fold(acc, item) } +} + +fn inspect_try_fold<'a, T, Acc, R>( + f: &'a mut impl FnMut(&T), + mut fold: impl FnMut(Acc, T) -> R + 'a, +) -> impl FnMut(Acc, T) -> R + 'a { + move |acc, item| { f(&item); fold(acc, item) } +} + #[stable(feature = "rust1", since = "1.0.0")] impl<I: Iterator, F> Iterator for Inspect<I, F> where F: FnMut(&I::Item) { type Item = I::Item; @@ -2120,19 +2280,17 @@ impl<I: Iterator, F> Iterator for Inspect<I, F> where F: FnMut(&I::Item) { } #[inline] - fn try_fold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where + fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> { - let f = &mut self.f; - self.iter.try_fold(init, move |acc, item| { f(&item); fold(acc, item) }) + self.iter.try_fold(init, inspect_try_fold(&mut self.f, fold)) } #[inline] - fn fold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc + fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { - let mut f = self.f; - self.iter.fold(init, move |acc, item| { f(&item); fold(acc, item) }) + self.iter.fold(init, inspect_fold(self.f, fold)) } } @@ -2147,19 +2305,17 @@ impl<I: DoubleEndedIterator, F> DoubleEndedIterator for Inspect<I, F> } #[inline] - fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, mut fold: Fold) -> R where + fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc> { - let f = &mut self.f; - self.iter.try_rfold(init, move |acc, item| { f(&item); fold(acc, item) }) + self.iter.try_rfold(init, inspect_try_fold(&mut self.f, fold)) } #[inline] - fn rfold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc + fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { - let mut f = self.f; - self.iter.rfold(init, move |acc, item| { f(&item); fold(acc, item) }) + self.iter.rfold(init, inspect_fold(self.f, fold)) } } diff --git a/src/libcore/iter/adapters/zip.rs b/src/libcore/iter/adapters/zip.rs index 06f047d9287..430ceacdd9f 100644 --- a/src/libcore/iter/adapters/zip.rs +++ b/src/libcore/iter/adapters/zip.rs @@ -94,11 +94,9 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B> #[inline] default fn next(&mut self) -> Option<(A::Item, B::Item)> { - self.a.next().and_then(|x| { - self.b.next().and_then(|y| { - Some((x, y)) - }) - }) + let x = self.a.next()?; + let y = self.b.next()?; + Some((x, y)) } #[inline] diff --git a/src/libcore/iter/sources.rs b/src/libcore/iter/sources.rs index 70a3b70c180..183176005ed 100644 --- a/src/libcore/iter/sources.rs +++ b/src/libcore/iter/sources.rs @@ -394,7 +394,8 @@ impl<A, F: FnOnce() -> A> Iterator for OnceWith<F> { #[inline] fn next(&mut self) -> Option<A> { - self.gen.take().map(|f| f()) + let f = self.gen.take()?; + Some(f()) } #[inline] @@ -608,10 +609,9 @@ impl<T, F> Iterator for Successors<T, F> #[inline] fn next(&mut self) -> Option<Self::Item> { - self.next.take().map(|item| { - self.next = (self.succ)(&item); - item - }) + let item = self.next.take()?; + self.next = (self.succ)(&item); + Some(item) } #[inline] diff --git a/src/libcore/iter/traits/accum.rs b/src/libcore/iter/traits/accum.rs index 812463e77f9..818f0330329 100644 --- a/src/libcore/iter/traits/accum.rs +++ b/src/libcore/iter/traits/accum.rs @@ -85,28 +85,28 @@ macro_rules! float_sum_product { #[stable(feature = "iter_arith_traits", since = "1.12.0")] impl Sum for $a { fn sum<I: Iterator<Item=$a>>(iter: I) -> $a { - iter.fold(0.0, |a, b| a + b) + iter.fold(0.0, Add::add) } } #[stable(feature = "iter_arith_traits", since = "1.12.0")] impl Product for $a { fn product<I: Iterator<Item=$a>>(iter: I) -> $a { - iter.fold(1.0, |a, b| a * b) + iter.fold(1.0, Mul::mul) } } #[stable(feature = "iter_arith_traits", since = "1.12.0")] impl<'a> Sum<&'a $a> for $a { fn sum<I: Iterator<Item=&'a $a>>(iter: I) -> $a { - iter.fold(0.0, |a, b| a + *b) + iter.fold(0.0, Add::add) } } #[stable(feature = "iter_arith_traits", since = "1.12.0")] impl<'a> Product<&'a $a> for $a { fn product<I: Iterator<Item=&'a $a>>(iter: I) -> $a { - iter.fold(1.0, |a, b| a * *b) + iter.fold(1.0, Mul::mul) } } )*) diff --git a/src/libcore/iter/traits/double_ended.rs b/src/libcore/iter/traits/double_ended.rs index 2c1aeb5690a..006b243ca42 100644 --- a/src/libcore/iter/traits/double_ended.rs +++ b/src/libcore/iter/traits/double_ended.rs @@ -69,7 +69,7 @@ pub trait DoubleEndedIterator: Iterator { /// Returns the `n`th element from the end of the iterator. /// /// This is essentially the reversed version of [`nth`]. Although like most indexing - /// operations, the count starts from zero, so `nth_back(0)` returns the first value fro + /// operations, the count starts from zero, so `nth_back(0)` returns the first value from /// the end, `nth_back(1)` the second, and so on. /// /// Note that all elements between the end and the returned element will be @@ -219,12 +219,17 @@ pub trait DoubleEndedIterator: Iterator { /// ``` #[inline] #[stable(feature = "iter_rfold", since = "1.27.0")] - fn rfold<B, F>(mut self, accum: B, mut f: F) -> B + fn rfold<B, F>(mut self, accum: B, f: F) -> B where Self: Sized, F: FnMut(B, Self::Item) -> B, { - self.try_rfold(accum, move |acc, x| Ok::<B, !>(f(acc, x))).unwrap() + #[inline] + fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> { + move |acc, x| Ok(f(acc, x)) + } + + self.try_rfold(accum, ok(f)).unwrap() } /// Searches for an element of an iterator from the back that satisfies a predicate. @@ -271,15 +276,21 @@ pub trait DoubleEndedIterator: Iterator { /// ``` #[inline] #[stable(feature = "iter_rfind", since = "1.27.0")] - fn rfind<P>(&mut self, mut predicate: P) -> Option<Self::Item> + fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item> where Self: Sized, P: FnMut(&Self::Item) -> bool { - self.try_rfold((), move |(), x| { - if predicate(&x) { LoopState::Break(x) } - else { LoopState::Continue(()) } - }).break_value() + #[inline] + fn check<T>( + mut predicate: impl FnMut(&T) -> bool, + ) -> impl FnMut((), T) -> LoopState<(), T> { + move |(), x| { + if predicate(&x) { LoopState::Break(x) } else { LoopState::Continue(()) } + } + } + + self.try_rfold((), check(predicate)).break_value() } } diff --git a/src/libcore/iter/traits/iterator.rs b/src/libcore/iter/traits/iterator.rs index 7e941267ce8..d644787d2c4 100644 --- a/src/libcore/iter/traits/iterator.rs +++ b/src/libcore/iter/traits/iterator.rs @@ -1,5 +1,5 @@ use crate::cmp::Ordering; -use crate::ops::Try; +use crate::ops::{Add, Try}; use super::super::LoopState; use super::super::{Chain, Cycle, Copied, Cloned, Enumerate, Filter, FilterMap, Fuse}; @@ -234,11 +234,15 @@ pub trait Iterator { /// assert_eq!(a.iter().count(), 5); /// ``` #[inline] - #[rustc_inherit_overflow_checks] #[stable(feature = "rust1", since = "1.0.0")] fn count(self) -> usize where Self: Sized { - // Might overflow. - self.fold(0, |cnt, _| cnt + 1) + #[inline] + fn add1<T>(count: usize, _: T) -> usize { + // Might overflow. + Add::add(count, 1) + } + + self.fold(0, add1) } /// Consumes the iterator, returning the last element. @@ -263,7 +267,12 @@ pub trait Iterator { #[inline] #[stable(feature = "rust1", since = "1.0.0")] fn last(self) -> Option<Self::Item> where Self: Sized { - self.fold(None, |_, x| Some(x)) + #[inline] + fn some<T>(_: Option<T>, x: T) -> Option<T> { + Some(x) + } + + self.fold(None, some) } /// Returns the `n`th element of the iterator. @@ -596,10 +605,15 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iterator_for_each", since = "1.21.0")] - fn for_each<F>(self, mut f: F) where + fn for_each<F>(self, f: F) where Self: Sized, F: FnMut(Self::Item), { - self.fold((), move |(), item| f(item)); + #[inline] + fn call<T>(mut f: impl FnMut(T)) -> impl FnMut((), T) { + move |(), item| f(item) + } + + self.fold((), call(f)); } /// Creates an iterator which uses a closure to determine if an element @@ -1490,21 +1504,30 @@ pub trait Iterator { /// assert_eq!(odd, vec![1, 3]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn partition<B, F>(self, mut f: F) -> (B, B) where + fn partition<B, F>(self, f: F) -> (B, B) where Self: Sized, B: Default + Extend<Self::Item>, F: FnMut(&Self::Item) -> bool { + #[inline] + fn extend<'a, T, B: Extend<T>>( + mut f: impl FnMut(&T) -> bool + 'a, + left: &'a mut B, + right: &'a mut B, + ) -> impl FnMut(T) + 'a { + move |x| { + if f(&x) { + left.extend(Some(x)); + } else { + right.extend(Some(x)); + } + } + } + let mut left: B = Default::default(); let mut right: B = Default::default(); - self.for_each(|x| { - if f(&x) { - left.extend(Some(x)) - } else { - right.extend(Some(x)) - } - }); + self.for_each(extend(f, &mut left, &mut right)); (left, right) } @@ -1702,10 +1725,15 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iterator_try_fold", since = "1.27.0")] - fn try_for_each<F, R>(&mut self, mut f: F) -> R where + fn try_for_each<F, R>(&mut self, f: F) -> R where Self: Sized, F: FnMut(Self::Item) -> R, R: Try<Ok=()> { - self.try_fold((), move |(), x| f(x)) + #[inline] + fn call<T, R>(mut f: impl FnMut(T) -> R) -> impl FnMut((), T) -> R { + move |(), x| f(x) + } + + self.try_fold((), call(f)) } /// An iterator method that applies a function, producing a single, final value. @@ -1777,10 +1805,15 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn fold<B, F>(mut self, init: B, mut f: F) -> B where + fn fold<B, F>(mut self, init: B, f: F) -> B where Self: Sized, F: FnMut(B, Self::Item) -> B, { - self.try_fold(init, move |acc, x| Ok::<B, !>(f(acc, x))).unwrap() + #[inline] + fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> { + move |acc, x| Ok(f(acc, x)) + } + + self.try_fold(init, ok(f)).unwrap() } /// Tests if every element of the iterator matches a predicate. @@ -1822,13 +1855,18 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn all<F>(&mut self, mut f: F) -> bool where + fn all<F>(&mut self, f: F) -> bool where Self: Sized, F: FnMut(Self::Item) -> bool { - self.try_for_each(move |x| { - if f(x) { LoopState::Continue(()) } - else { LoopState::Break(()) } - }) == LoopState::Continue(()) + #[inline] + fn check<T>(mut f: impl FnMut(T) -> bool) -> impl FnMut(T) -> LoopState<(), ()> { + move |x| { + if f(x) { LoopState::Continue(()) } + else { LoopState::Break(()) } + } + } + + self.try_for_each(check(f)) == LoopState::Continue(()) } /// Tests if any element of the iterator matches a predicate. @@ -1870,14 +1908,19 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn any<F>(&mut self, mut f: F) -> bool where + fn any<F>(&mut self, f: F) -> bool where Self: Sized, F: FnMut(Self::Item) -> bool { - self.try_for_each(move |x| { - if f(x) { LoopState::Break(()) } - else { LoopState::Continue(()) } - }) == LoopState::Break(()) + #[inline] + fn check<T>(mut f: impl FnMut(T) -> bool) -> impl FnMut(T) -> LoopState<(), ()> { + move |x| { + if f(x) { LoopState::Break(()) } + else { LoopState::Continue(()) } + } + } + + self.try_for_each(check(f)) == LoopState::Break(()) } /// Searches for an element of an iterator that satisfies a predicate. @@ -1924,14 +1967,19 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn find<P>(&mut self, mut predicate: P) -> Option<Self::Item> where + fn find<P>(&mut self, predicate: P) -> Option<Self::Item> where Self: Sized, P: FnMut(&Self::Item) -> bool, { - self.try_for_each(move |x| { - if predicate(&x) { LoopState::Break(x) } - else { LoopState::Continue(()) } - }).break_value() + #[inline] + fn check<T>(mut predicate: impl FnMut(&T) -> bool) -> impl FnMut(T) -> LoopState<(), T> { + move |x| { + if predicate(&x) { LoopState::Break(x) } + else { LoopState::Continue(()) } + } + } + + self.try_for_each(check(predicate)).break_value() } /// Applies function to the elements of iterator and returns @@ -1951,16 +1999,19 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iterator_find_map", since = "1.30.0")] - fn find_map<B, F>(&mut self, mut f: F) -> Option<B> where + fn find_map<B, F>(&mut self, f: F) -> Option<B> where Self: Sized, F: FnMut(Self::Item) -> Option<B>, { - self.try_for_each(move |x| { - match f(x) { + #[inline] + fn check<T, B>(mut f: impl FnMut(T) -> Option<B>) -> impl FnMut(T) -> LoopState<(), B> { + move |x| match f(x) { Some(x) => LoopState::Break(x), None => LoopState::Continue(()), } - }).break_value() + } + + self.try_for_each(check(f)).break_value() } /// Searches for an element in an iterator, returning its index. @@ -2018,17 +2069,23 @@ pub trait Iterator { /// /// ``` #[inline] - #[rustc_inherit_overflow_checks] #[stable(feature = "rust1", since = "1.0.0")] - fn position<P>(&mut self, mut predicate: P) -> Option<usize> where + fn position<P>(&mut self, predicate: P) -> Option<usize> where Self: Sized, P: FnMut(Self::Item) -> bool, { - // The addition might panic on overflow - self.try_fold(0, move |i, x| { - if predicate(x) { LoopState::Break(i) } - else { LoopState::Continue(i + 1) } - }).break_value() + #[inline] + fn check<T>( + mut predicate: impl FnMut(T) -> bool, + ) -> impl FnMut(usize, T) -> LoopState<usize, usize> { + // The addition might panic on overflow + move |i, x| { + if predicate(x) { LoopState::Break(i) } + else { LoopState::Continue(Add::add(i, 1)) } + } + } + + self.try_fold(0, check(predicate)).break_value() } /// Searches for an element in an iterator from the right, returning its @@ -2071,18 +2128,25 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn rposition<P>(&mut self, mut predicate: P) -> Option<usize> where + fn rposition<P>(&mut self, predicate: P) -> Option<usize> where P: FnMut(Self::Item) -> bool, Self: Sized + ExactSizeIterator + DoubleEndedIterator { // No need for an overflow check here, because `ExactSizeIterator` // implies that the number of elements fits into a `usize`. + #[inline] + fn check<T>( + mut predicate: impl FnMut(T) -> bool, + ) -> impl FnMut(usize, T) -> LoopState<usize, usize> { + move |i, x| { + let i = i - 1; + if predicate(x) { LoopState::Break(i) } + else { LoopState::Continue(i) } + } + } + let n = self.len(); - self.try_rfold(n, move |i, x| { - let i = i - 1; - if predicate(x) { LoopState::Break(i) } - else { LoopState::Continue(i) } - }).break_value() + self.try_rfold(n, check(predicate)).break_value() } /// Returns the maximum element of an iterator. @@ -2151,11 +2215,22 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iter_cmp_by_key", since = "1.6.0")] - fn max_by_key<B: Ord, F>(self, mut f: F) -> Option<Self::Item> + fn max_by_key<B: Ord, F>(self, f: F) -> Option<Self::Item> where Self: Sized, F: FnMut(&Self::Item) -> B, { + #[inline] + fn key<T, B>(mut f: impl FnMut(&T) -> B) -> impl FnMut(T) -> (B, T) { + move |x| (f(&x), x) + } + // switch to y even if it is only equal, to preserve stability. - select_fold1(self.map(|x| (f(&x), x)), |(x_p, _), (y_p, _)| x_p <= y_p).map(|(_, x)| x) + #[inline] + fn select<T, B: Ord>((x_p, _): &(B, T), (y_p, _): &(B, T)) -> bool { + x_p <= y_p + } + + let (_, x) = select_fold1(self.map(key(f)), select)?; + Some(x) } /// Returns the element that gives the maximum value with respect to the @@ -2174,11 +2249,16 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iter_max_by", since = "1.15.0")] - fn max_by<F>(self, mut compare: F) -> Option<Self::Item> + fn max_by<F>(self, compare: F) -> Option<Self::Item> where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering, { // switch to y even if it is only equal, to preserve stability. - select_fold1(self, |x, y| compare(x, y) != Ordering::Greater) + #[inline] + fn select<T>(mut compare: impl FnMut(&T, &T) -> Ordering) -> impl FnMut(&T, &T) -> bool { + move |x, y| compare(x, y) != Ordering::Greater + } + + select_fold1(self, select(compare)) } /// Returns the element that gives the minimum value from the @@ -2195,12 +2275,24 @@ pub trait Iterator { /// let a = [-3_i32, 0, 1, 5, -10]; /// assert_eq!(*a.iter().min_by_key(|x| x.abs()).unwrap(), 0); /// ``` + #[inline] #[stable(feature = "iter_cmp_by_key", since = "1.6.0")] - fn min_by_key<B: Ord, F>(self, mut f: F) -> Option<Self::Item> + fn min_by_key<B: Ord, F>(self, f: F) -> Option<Self::Item> where Self: Sized, F: FnMut(&Self::Item) -> B, { + #[inline] + fn key<T, B>(mut f: impl FnMut(&T) -> B) -> impl FnMut(T) -> (B, T) { + move |x| (f(&x), x) + } + // only switch to y if it is strictly smaller, to preserve stability. - select_fold1(self.map(|x| (f(&x), x)), |(x_p, _), (y_p, _)| x_p > y_p).map(|(_, x)| x) + #[inline] + fn select<T, B: Ord>((x_p, _): &(B, T), (y_p, _): &(B, T)) -> bool { + x_p > y_p + } + + let (_, x) = select_fold1(self.map(key(f)), select)?; + Some(x) } /// Returns the element that gives the minimum value with respect to the @@ -2219,11 +2311,16 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iter_min_by", since = "1.15.0")] - fn min_by<F>(self, mut compare: F) -> Option<Self::Item> + fn min_by<F>(self, compare: F) -> Option<Self::Item> where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering, { // only switch to y if it is strictly smaller, to preserve stability. - select_fold1(self, |x, y| compare(x, y) == Ordering::Greater) + #[inline] + fn select<T>(mut compare: impl FnMut(&T, &T) -> Ordering) -> impl FnMut(&T, &T) -> bool { + move |x, y| compare(x, y) == Ordering::Greater + } + + select_fold1(self, select(compare)) } @@ -2284,13 +2381,20 @@ pub trait Iterator { FromB: Default + Extend<B>, Self: Sized + Iterator<Item=(A, B)>, { + fn extend<'a, A, B>( + ts: &'a mut impl Extend<A>, + us: &'a mut impl Extend<B>, + ) -> impl FnMut((A, B)) + 'a { + move |(t, u)| { + ts.extend(Some(t)); + us.extend(Some(u)); + } + } + let mut ts: FromA = Default::default(); let mut us: FromB = Default::default(); - self.for_each(|(t, u)| { - ts.extend(Some(t)); - us.extend(Some(u)); - }); + self.for_each(extend(&mut ts, &mut us)); (ts, us) } @@ -2617,7 +2721,7 @@ pub trait Iterator { Self: Sized, Self::Item: PartialOrd, { - self.is_sorted_by(|a, b| a.partial_cmp(b)) + self.is_sorted_by(PartialOrd::partial_cmp) } /// Checks if the elements of this iterator are sorted using the given comparator function. @@ -2639,10 +2743,7 @@ pub trait Iterator { }; while let Some(curr) = self.next() { - if compare(&last, &curr) - .map(|o| o == Ordering::Greater) - .unwrap_or(true) - { + if let Some(Ordering::Greater) | None = compare(&last, &curr) { return false; } last = curr; @@ -2687,17 +2788,21 @@ pub trait Iterator { /// commonalities of {max,min}{,_by}. In particular, this avoids /// having to implement optimizations several times. #[inline] -fn select_fold1<I, F>(mut it: I, mut f: F) -> Option<I::Item> +fn select_fold1<I, F>(mut it: I, f: F) -> Option<I::Item> where I: Iterator, F: FnMut(&I::Item, &I::Item) -> bool, { + #[inline] + fn select<T>(mut f: impl FnMut(&T, &T) -> bool) -> impl FnMut(T, T) -> T { + move |sel, x| if f(&sel, &x) { x } else { sel } + } + // start with the first element as our selection. This avoids // having to use `Option`s inside the loop, translating to a // sizeable performance gain (6x in one case). - it.next().map(|first| { - it.fold(first, |sel, x| if f(&sel, &x) { x } else { sel }) - }) + let first = it.next()?; + Some(it.fold(first, select(f))) } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 678ff768792..c168d5c8a2e 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -63,7 +63,7 @@ #![warn(missing_debug_implementations)] #![deny(intra_doc_link_resolution_failure)] // rustdoc is run without -D warnings #![allow(explicit_outlives_requirements)] -#![cfg_attr(not(bootstrap), allow(incomplete_features))] +#![allow(incomplete_features)] #![feature(allow_internal_unstable)] #![feature(arbitrary_self_types)] @@ -129,7 +129,7 @@ #![feature(structural_match)] #![feature(abi_unadjusted)] #![feature(adx_target_feature)] -#![feature(maybe_uninit_slice, maybe_uninit_array)] +#![feature(maybe_uninit_slice)] #![feature(external_doc)] #![feature(mem_take)] #![feature(associated_type_bounds)] diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index f9dc53874ac..6c88a766a2f 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -2,21 +2,21 @@ /// /// For details, see `std::macros`. #[macro_export] -#[allow_internal_unstable(core_panic, __rust_unstable_column)] +#[allow_internal_unstable(core_panic)] #[stable(feature = "core", since = "1.6.0")] macro_rules! panic { () => ( $crate::panic!("explicit panic") ); ($msg:expr) => ({ - $crate::panicking::panic(&($msg, file!(), line!(), __rust_unstable_column!())) + $crate::panicking::panic(&($msg, $crate::file!(), $crate::line!(), $crate::column!())) }); ($msg:expr,) => ( $crate::panic!($msg) ); ($fmt:expr, $($arg:tt)+) => ({ - $crate::panicking::panic_fmt(format_args!($fmt, $($arg)+), - &(file!(), line!(), __rust_unstable_column!())) + $crate::panicking::panic_fmt($crate::format_args!($fmt, $($arg)+), + &($crate::file!(), $crate::line!(), $crate::column!())) }); } @@ -70,7 +70,7 @@ macro_rules! assert_eq { panic!(r#"assertion failed: `(left == right)` left: `{:?}`, right: `{:?}`: {}"#, &*left_val, &*right_val, - format_args!($($arg)+)) + $crate::format_args!($($arg)+)) } } } @@ -127,7 +127,7 @@ macro_rules! assert_ne { panic!(r#"assertion failed: `(left != right)` left: `{:?}`, right: `{:?}`: {}"#, &*left_val, &*right_val, - format_args!($($arg)+)) + $crate::format_args!($($arg)+)) } } } @@ -181,7 +181,7 @@ macro_rules! assert_ne { #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] macro_rules! debug_assert { - ($($arg:tt)*) => (if cfg!(debug_assertions) { assert!($($arg)*); }) + ($($arg:tt)*) => (if $crate::cfg!(debug_assertions) { $crate::assert!($($arg)*); }) } /// Asserts that two expressions are equal to each other. @@ -208,7 +208,7 @@ macro_rules! debug_assert { #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] macro_rules! debug_assert_eq { - ($($arg:tt)*) => (if cfg!(debug_assertions) { $crate::assert_eq!($($arg)*); }) + ($($arg:tt)*) => (if $crate::cfg!(debug_assertions) { $crate::assert_eq!($($arg)*); }) } /// Asserts that two expressions are not equal to each other. @@ -235,7 +235,7 @@ macro_rules! debug_assert_eq { #[macro_export] #[stable(feature = "assert_ne", since = "1.13.0")] macro_rules! debug_assert_ne { - ($($arg:tt)*) => (if cfg!(debug_assertions) { $crate::assert_ne!($($arg)*); }) + ($($arg:tt)*) => (if $crate::cfg!(debug_assertions) { $crate::assert_ne!($($arg)*); }) } /// Unwraps a result or propagates its error. @@ -386,7 +386,7 @@ macro_rules! r#try { #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] macro_rules! write { - ($dst:expr, $($arg:tt)*) => ($dst.write_fmt(format_args!($($arg)*))) + ($dst:expr, $($arg:tt)*) => ($dst.write_fmt($crate::format_args!($($arg)*))) } /// Write formatted data into a buffer, with a newline appended. @@ -446,7 +446,7 @@ macro_rules! writeln { $crate::writeln!($dst) ); ($dst:expr, $($arg:tt)*) => ( - $dst.write_fmt(format_args_nl!($($arg)*)) + $dst.write_fmt($crate::format_args_nl!($($arg)*)) ); } @@ -515,7 +515,7 @@ macro_rules! unreachable { $crate::unreachable!($msg) }); ($fmt:expr, $($arg:tt)*) => ({ - panic!(concat!("internal error: entered unreachable code: ", $fmt), $($arg)*) + panic!($crate::concat!("internal error: entered unreachable code: ", $fmt), $($arg)*) }); } @@ -573,7 +573,7 @@ macro_rules! unreachable { #[stable(feature = "rust1", since = "1.0.0")] macro_rules! unimplemented { () => (panic!("not yet implemented")); - ($($arg:tt)+) => (panic!("not yet implemented: {}", format_args!($($arg)+))); + ($($arg:tt)+) => (panic!("not yet implemented: {}", $crate::format_args!($($arg)+))); } /// Indicates unfinished code. @@ -632,41 +632,7 @@ macro_rules! unimplemented { #[unstable(feature = "todo_macro", issue = "59277")] macro_rules! todo { () => (panic!("not yet implemented")); - ($($arg:tt)+) => (panic!("not yet implemented: {}", format_args!($($arg)+))); -} - -/// Creates an array of [`MaybeUninit`]. -/// -/// This macro constructs an uninitialized array of the type `[MaybeUninit<K>; N]`. -/// It exists solely because bootstrap does not yet support const array-init expressions. -/// -/// [`MaybeUninit`]: mem/union.MaybeUninit.html -// FIXME: Remove both versions of this macro once bootstrap is 1.38. -#[macro_export] -#[unstable(feature = "maybe_uninit_array", issue = "53491")] -#[cfg(bootstrap)] -macro_rules! uninit_array { - // This `assume_init` is safe because an array of `MaybeUninit` does not - // require initialization. - ($t:ty; $size:expr) => (unsafe { - MaybeUninit::<[MaybeUninit<$t>; $size]>::uninit().assume_init() - }); -} - -/// Creates an array of [`MaybeUninit`]. -/// -/// This macro constructs an uninitialized array of the type `[MaybeUninit<K>; N]`. -/// It exists solely because bootstrap does not yet support const array-init expressions. -/// -/// [`MaybeUninit`]: mem/union.MaybeUninit.html -// FIXME: Just inline this version of the macro once bootstrap is 1.38. -#[macro_export] -#[unstable(feature = "maybe_uninit_array", issue = "53491")] -#[cfg(not(bootstrap))] -macro_rules! uninit_array { - ($t:ty; $size:expr) => ( - [MaybeUninit::<$t>::UNINIT; $size] - ); + ($($arg:tt)+) => (panic!("not yet implemented: {}", $crate::format_args!($($arg)+))); } /// Definitions of built-in macros. @@ -674,7 +640,6 @@ macro_rules! uninit_array { /// Most of the macro properties (stability, visibility, etc.) are taken from the source code here, /// with exception of expansion functions transforming macro inputs into outputs, /// those functions are provided by the compiler. -#[cfg(not(bootstrap))] pub(crate) mod builtin { /// Causes compilation to fail with the given error message when encountered. @@ -962,13 +927,6 @@ pub(crate) mod builtin { #[macro_export] macro_rules! column { () => { /* compiler built-in */ } } - /// Same as `column`, but less likely to be shadowed. - #[unstable(feature = "__rust_unstable_column", issue = "0", - reason = "internal implementation detail of the `panic` macro")] - #[rustc_builtin_macro] - #[macro_export] - macro_rules! __rust_unstable_column { () => { /* compiler built-in */ } } - /// Expands to the file name in which it was invoked. /// /// With [`line!`] and [`column!`], these macros provide debugging information for @@ -1305,14 +1263,14 @@ pub(crate) mod builtin { /// Unstable implementation detail of the `rustc` compiler, do not use. #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] + #[cfg_attr(boostrap_stdarch_ignore_this, rustc_macro_transparency = "semitransparent")] #[stable(feature = "rust1", since = "1.0.0")] #[allow_internal_unstable(core_intrinsics, libstd_sys_internals)] pub macro RustcDecodable($item:item) { /* compiler built-in */ } /// Unstable implementation detail of the `rustc` compiler, do not use. #[rustc_builtin_macro] - #[rustc_macro_transparency = "semitransparent"] + #[cfg_attr(boostrap_stdarch_ignore_this, rustc_macro_transparency = "semitransparent")] #[stable(feature = "rust1", since = "1.0.0")] #[allow_internal_unstable(core_intrinsics)] pub macro RustcEncodable($item:item) { /* compiler built-in */ } diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index 78a27361165..89af2528c05 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -289,9 +289,8 @@ pub trait Copy : Clone { } /// Derive macro generating an impl of the trait `Copy`. -#[cfg(not(bootstrap))] #[rustc_builtin_macro] -#[rustc_macro_transparency = "semitransparent"] +#[cfg_attr(boostrap_stdarch_ignore_this, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics, derive_clone_copy)] pub macro Copy($item:item) { /* compiler built-in */ } diff --git a/src/libcore/mem/maybe_uninit.rs b/src/libcore/mem/maybe_uninit.rs index 1bbea02e0c7..9e9e901c76d 100644 --- a/src/libcore/mem/maybe_uninit.rs +++ b/src/libcore/mem/maybe_uninit.rs @@ -213,7 +213,7 @@ use crate::mem::ManuallyDrop; #[allow(missing_debug_implementations)] #[stable(feature = "maybe_uninit", since = "1.36.0")] // Lang item so we can wrap other types in it. This is useful for generators. -#[cfg_attr(not(bootstrap), lang = "maybe_uninit")] +#[lang = "maybe_uninit"] #[derive(Copy)] #[repr(transparent)] pub union MaybeUninit<T> { @@ -312,7 +312,7 @@ impl<T> MaybeUninit<T> { /// without dropping it, so be careful not to use this twice unless you want to /// skip running the destructor. For your convenience, this also returns a mutable /// reference to the (now safely initialized) contents of `self`. - #[unstable(feature = "maybe_uninit_extra", issue = "53491")] + #[unstable(feature = "maybe_uninit_extra", issue = "63567")] #[inline(always)] pub fn write(&mut self, val: T) -> &mut T { unsafe { @@ -502,7 +502,7 @@ impl<T> MaybeUninit<T> { /// // We now created two copies of the same vector, leading to a double-free when /// // they both get dropped! /// ``` - #[unstable(feature = "maybe_uninit_extra", issue = "53491")] + #[unstable(feature = "maybe_uninit_extra", issue = "63567")] #[inline(always)] pub unsafe fn read(&self) -> T { intrinsics::panic_if_uninhabited::<T>(); @@ -516,7 +516,7 @@ impl<T> MaybeUninit<T> { /// It is up to the caller to guarantee that the `MaybeUninit<T>` really is in an initialized /// state. Calling this when the content is not yet fully initialized causes undefined /// behavior. - #[unstable(feature = "maybe_uninit_ref", issue = "53491")] + #[unstable(feature = "maybe_uninit_ref", issue = "63568")] #[inline(always)] pub unsafe fn get_ref(&self) -> &T { &*self.value @@ -532,21 +532,21 @@ impl<T> MaybeUninit<T> { // FIXME(#53491): We currently rely on the above being incorrect, i.e., we have references // to uninitialized data (e.g., in `libcore/fmt/float.rs`). We should make // a final decision about the rules before stabilization. - #[unstable(feature = "maybe_uninit_ref", issue = "53491")] + #[unstable(feature = "maybe_uninit_ref", issue = "63568")] #[inline(always)] pub unsafe fn get_mut(&mut self) -> &mut T { &mut *self.value } /// Gets a pointer to the first element of the array. - #[unstable(feature = "maybe_uninit_slice", issue = "53491")] + #[unstable(feature = "maybe_uninit_slice", issue = "63569")] #[inline(always)] pub fn first_ptr(this: &[MaybeUninit<T>]) -> *const T { this as *const [MaybeUninit<T>] as *const T } /// Gets a mutable pointer to the first element of the array. - #[unstable(feature = "maybe_uninit_slice", issue = "53491")] + #[unstable(feature = "maybe_uninit_slice", issue = "63569")] #[inline(always)] pub fn first_ptr_mut(this: &mut [MaybeUninit<T>]) -> *mut T { this as *mut [MaybeUninit<T>] as *mut T diff --git a/src/libcore/mem/mod.rs b/src/libcore/mem/mod.rs index 2534400b833..87ec05a243d 100644 --- a/src/libcore/mem/mod.rs +++ b/src/libcore/mem/mod.rs @@ -453,7 +453,7 @@ pub const fn needs_drop<T>() -> bool { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(bootstrap, allow(deprecated_in_future))] +#[allow(deprecated_in_future)] #[allow(deprecated)] pub unsafe fn zeroed<T>() -> T { intrinsics::panic_if_uninhabited::<T>(); @@ -481,7 +481,7 @@ pub unsafe fn zeroed<T>() -> T { #[inline] #[rustc_deprecated(since = "1.39.0", reason = "use `mem::MaybeUninit` instead")] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(bootstrap, allow(deprecated_in_future))] +#[allow(deprecated_in_future)] #[allow(deprecated)] pub unsafe fn uninitialized<T>() -> T { intrinsics::panic_if_uninhabited::<T>(); diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 67e30e7ffcb..b46e06f8d8a 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -1112,7 +1112,13 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn wrapping_add(self, rhs: Self) -> Self { - intrinsics::overflowing_add(self, rhs) + #[cfg(boostrap_stdarch_ignore_this)] { + intrinsics::overflowing_add(self, rhs) + } + + #[cfg(not(boostrap_stdarch_ignore_this))] { + intrinsics::wrapping_add(self, rhs) + } } } @@ -1135,7 +1141,13 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn wrapping_sub(self, rhs: Self) -> Self { - intrinsics::overflowing_sub(self, rhs) + #[cfg(boostrap_stdarch_ignore_this)] { + intrinsics::overflowing_sub(self, rhs) + } + + #[cfg(not(boostrap_stdarch_ignore_this))] { + intrinsics::wrapping_sub(self, rhs) + } } } @@ -1157,7 +1169,13 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn wrapping_mul(self, rhs: Self) -> Self { - intrinsics::overflowing_mul(self, rhs) + #[cfg(boostrap_stdarch_ignore_this)] { + intrinsics::overflowing_mul(self, rhs) + } + + #[cfg(not(boostrap_stdarch_ignore_this))] { + intrinsics::wrapping_mul(self, rhs) + } } } @@ -3031,7 +3049,13 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn wrapping_add(self, rhs: Self) -> Self { - intrinsics::overflowing_add(self, rhs) + #[cfg(boostrap_stdarch_ignore_this)] { + intrinsics::overflowing_add(self, rhs) + } + + #[cfg(not(boostrap_stdarch_ignore_this))] { + intrinsics::wrapping_add(self, rhs) + } } } @@ -3053,7 +3077,13 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn wrapping_sub(self, rhs: Self) -> Self { - intrinsics::overflowing_sub(self, rhs) + #[cfg(boostrap_stdarch_ignore_this)] { + intrinsics::overflowing_sub(self, rhs) + } + + #[cfg(not(boostrap_stdarch_ignore_this))] { + intrinsics::wrapping_sub(self, rhs) + } } } @@ -3076,7 +3106,13 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn wrapping_mul(self, rhs: Self) -> Self { - intrinsics::overflowing_mul(self, rhs) + #[cfg(boostrap_stdarch_ignore_this)] { + intrinsics::overflowing_mul(self, rhs) + } + + #[cfg(not(boostrap_stdarch_ignore_this))] { + intrinsics::wrapping_mul(self, rhs) + } } doc_comment! { diff --git a/src/libcore/prelude/v1.rs b/src/libcore/prelude/v1.rs index 84cf85f339c..7cc279a9ef2 100644 --- a/src/libcore/prelude/v1.rs +++ b/src/libcore/prelude/v1.rs @@ -46,20 +46,16 @@ pub use crate::option::Option::{self, Some, None}; pub use crate::result::Result::{self, Ok, Err}; // Re-exported built-in macros -#[cfg(not(bootstrap))] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[doc(no_inline)] pub use crate::fmt::macros::Debug; -#[cfg(not(bootstrap))] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[doc(no_inline)] pub use crate::hash::macros::Hash; -#[cfg(not(bootstrap))] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[doc(no_inline)] pub use crate::{ - __rust_unstable_column, asm, assert, cfg, @@ -83,7 +79,6 @@ pub use crate::{ trace_macros, }; -#[cfg(not(bootstrap))] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow(deprecated)] #[doc(no_inline)] diff --git a/src/libcore/ptr/unique.rs b/src/libcore/ptr/unique.rs index f0d011fe6b2..3521dd79979 100644 --- a/src/libcore/ptr/unique.rs +++ b/src/libcore/ptr/unique.rs @@ -122,6 +122,14 @@ impl<T: ?Sized> Unique<T> { pub unsafe fn as_mut(&mut self) -> &mut T { &mut *self.as_ptr() } + + /// Casts to a pointer of another type. + #[inline] + pub const fn cast<U>(self) -> Unique<U> { + unsafe { + Unique::new_unchecked(self.as_ptr() as *mut U) + } + } } #[unstable(feature = "ptr_internals", issue = "0")] diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index ce5af13d4ca..bfbbb15c8d4 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -4637,6 +4637,22 @@ impl<'a, T> DoubleEndedIterator for ChunksExactMut<'a, T> { Some(tail) } } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option<Self::Item> { + let len = self.len(); + if n >= len { + self.v = &mut []; + None + } else { + let start = (len - 1 - n) * self.chunk_size; + let end = start + self.chunk_size; + let (temp, _tail) = mem::replace(&mut self.v, &mut []).split_at_mut(end); + let (head, nth_back) = temp.split_at_mut(start); + self.v = head; + Some(nth_back) + } + } } #[stable(feature = "chunks_exact", since = "1.31.0")] diff --git a/src/libcore/task/poll.rs b/src/libcore/task/poll.rs index 3db70d5e764..fec17c4d1a4 100644 --- a/src/libcore/task/poll.rs +++ b/src/libcore/task/poll.rs @@ -81,6 +81,34 @@ impl<T, E> Poll<Result<T, E>> { } } +impl<T, E> Poll<Option<Result<T, E>>> { + /// Changes the success value of this `Poll` with the closure provided. + #[unstable(feature = "poll_map", issue = "63514")] + pub fn map_ok<U, F>(self, f: F) -> Poll<Option<Result<U, E>>> + where F: FnOnce(T) -> U + { + match self { + Poll::Ready(Some(Ok(t))) => Poll::Ready(Some(Ok(f(t)))), + Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(e))), + Poll::Ready(None) => Poll::Ready(None), + Poll::Pending => Poll::Pending, + } + } + + /// Changes the error value of this `Poll` with the closure provided. + #[unstable(feature = "poll_map", issue = "63514")] + pub fn map_err<U, F>(self, f: F) -> Poll<Option<Result<T, U>>> + where F: FnOnce(E) -> U + { + match self { + Poll::Ready(Some(Ok(t))) => Poll::Ready(Some(Ok(t))), + Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(f(e)))), + Poll::Ready(None) => Poll::Ready(None), + Poll::Pending => Poll::Pending, + } + } +} + #[stable(feature = "futures_api", since = "1.36.0")] impl<T> From<T> for Poll<T> { fn from(t: T) -> Poll<T> { diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index 3615fab7915..3a4f76852a0 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -104,6 +104,22 @@ fn test_iterator_chain_nth() { } #[test] +fn test_iterator_chain_nth_back() { + let xs = [0, 1, 2, 3, 4, 5]; + let ys = [30, 40, 50, 60]; + let zs = []; + let expected = [0, 1, 2, 3, 4, 5, 30, 40, 50, 60]; + for (i, x) in expected.iter().rev().enumerate() { + assert_eq!(Some(x), xs.iter().chain(&ys).nth_back(i)); + } + assert_eq!(zs.iter().chain(&xs).nth_back(0), Some(&5)); + + let mut it = xs.iter().chain(&zs); + assert_eq!(it.nth_back(5), Some(&0)); + assert_eq!(it.next(), None); +} + +#[test] fn test_iterator_chain_last() { let xs = [0, 1, 2, 3, 4, 5]; let ys = [30, 40, 50, 60]; @@ -137,6 +153,54 @@ fn test_iterator_chain_find() { } #[test] +fn test_iterator_chain_size_hint() { + struct Iter { + is_empty: bool, + } + + impl Iterator for Iter { + type Item = (); + + // alternates between `None` and `Some(())` + fn next(&mut self) -> Option<Self::Item> { + if self.is_empty { + self.is_empty = false; + None + } else { + self.is_empty = true; + Some(()) + } + } + + fn size_hint(&self) -> (usize, Option<usize>) { + if self.is_empty { + (0, Some(0)) + } else { + (1, Some(1)) + } + } + } + + impl DoubleEndedIterator for Iter { + fn next_back(&mut self) -> Option<Self::Item> { + self.next() + } + } + + // this chains an iterator of length 0 with an iterator of length 1, + // so after calling `.next()` once, the iterator is empty and the + // state is `ChainState::Back`. `.size_hint()` should now disregard + // the size hint of the left iterator + let mut iter = Iter { is_empty: true }.chain(once(())); + assert_eq!(iter.next(), Some(())); + assert_eq!(iter.size_hint(), (0, Some(0))); + + let mut iter = once(()).chain(Iter { is_empty: true }); + assert_eq!(iter.next_back(), Some(())); + assert_eq!(iter.size_hint(), (0, Some(0))); +} + +#[test] fn test_zip_nth() { let xs = [0, 1, 2, 4, 5]; let ys = [10, 11, 12]; @@ -1136,6 +1200,18 @@ fn test_cycle() { assert_eq!(empty::<i32>().cycle().fold(0, |acc, x| acc + x), 0); assert_eq!(once(1).cycle().skip(1).take(4).fold(0, |acc, x| acc + x), 4); + + assert_eq!((0..10).cycle().take(5).sum::<i32>(), 10); + assert_eq!((0..10).cycle().take(15).sum::<i32>(), 55); + assert_eq!((0..10).cycle().take(25).sum::<i32>(), 100); + + let mut iter = (0..10).cycle(); + iter.nth(14); + assert_eq!(iter.take(8).sum::<i32>(), 38); + + let mut iter = (0..10).cycle(); + iter.nth(9); + assert_eq!(iter.take(3).sum::<i32>(), 3); } #[test] diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs index 4790152512a..6609bc3135a 100644 --- a/src/libcore/tests/slice.rs +++ b/src/libcore/tests/slice.rs @@ -375,6 +375,25 @@ fn test_chunks_exact_mut_nth() { } #[test] +fn test_chunks_exact_mut_nth_back() { + let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5]; + let mut c = v.chunks_exact_mut(2); + assert_eq!(c.nth_back(1).unwrap(), &[2, 3]); + assert_eq!(c.next().unwrap(), &[0, 1]); + assert_eq!(c.next(), None); + + let v2: &mut [i32] = &mut [0, 1, 2, 3, 4]; + let mut c2 = v2.chunks_exact_mut(3); + assert_eq!(c2.nth_back(0).unwrap(), &[0, 1, 2]); + assert_eq!(c2.next(), None); + assert_eq!(c2.next_back(), None); + + let v3: &mut [i32] = &mut [0, 1, 2, 3, 4]; + let mut c3 = v3.chunks_exact_mut(10); + assert_eq!(c3.nth_back(0), None); +} + +#[test] fn test_chunks_exact_mut_last() { let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5]; let c = v.chunks_exact_mut(2); diff --git a/src/libproc_macro/bridge/client.rs b/src/libproc_macro/bridge/client.rs index 6052b4a4d43..5c543165bc2 100644 --- a/src/libproc_macro/bridge/client.rs +++ b/src/libproc_macro/bridge/client.rs @@ -468,6 +468,14 @@ pub enum ProcMacro { } impl ProcMacro { + pub fn name(&self) -> &'static str { + match self { + ProcMacro::CustomDerive { trait_name, .. } => trait_name, + ProcMacro::Attr { name, .. } => name, + ProcMacro::Bang { name, ..} => name + } + } + pub const fn custom_derive( trait_name: &'static str, attributes: &'static [&'static str], diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs index ca852fe7622..0dad2dda837 100644 --- a/src/librustc/cfg/construct.rs +++ b/src/librustc/cfg/construct.rs @@ -136,10 +136,15 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { } PatKind::Struct(_, ref subpats, _) => { - let pats_exit = self.pats_all(subpats.iter().map(|f| &f.node.pat), pred); + let pats_exit = self.pats_all(subpats.iter().map(|f| &f.pat), pred); self.add_ast_node(pat.hir_id.local_id, &[pats_exit]) } + PatKind::Or(ref pats) => { + let branches: Vec<_> = pats.iter().map(|p| self.pat(p, pred)).collect(); + self.add_ast_node(pat.hir_id.local_id, &branches) + } + PatKind::Slice(ref pre, ref vec, ref post) => { let pre_exit = self.pats_all(pre.iter(), pred); let vec_exit = self.pats_all(vec.iter(), pre_exit); diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs index b3eee7c3464..a200a058f4f 100644 --- a/src/librustc/error_codes.rs +++ b/src/librustc/error_codes.rs @@ -2088,7 +2088,6 @@ generator can be constructed. Erroneous code example: ```edition2018,compile-fail,E0698 -#![feature(async_await)] async fn bar<T>() -> () {} async fn foo() { @@ -2101,7 +2100,6 @@ To fix this you must bind `T` to a concrete type such as `String` so that a generator can then be constructed: ```edition2018 -#![feature(async_await)] async fn bar<T>() -> () {} async fn foo() { diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs index 22124d4ee41..eae956c978a 100644 --- a/src/librustc/hir/check_attr.rs +++ b/src/librustc/hir/check_attr.rs @@ -336,7 +336,7 @@ impl Visitor<'tcx> for CheckAttrVisitor<'tcx> { fn is_c_like_enum(item: &hir::Item) -> bool { if let hir::ItemKind::Enum(ref def, _) = item.node { for variant in &def.variants { - match variant.node.data { + match variant.data { hir::VariantData::Unit(..) => { /* continue */ } _ => { return false; } } diff --git a/src/librustc/hir/def_id.rs b/src/librustc/hir/def_id.rs index c0a661908a6..c91ad7858d0 100644 --- a/src/librustc/hir/def_id.rs +++ b/src/librustc/hir/def_id.rs @@ -1,5 +1,4 @@ use crate::ty::{self, TyCtxt}; -use crate::hir::map::definitions::FIRST_FREE_DEF_INDEX; use rustc_data_structures::indexed_vec::Idx; use std::fmt; use std::u32; @@ -102,31 +101,6 @@ newtype_index! { } } -impl DefIndex { - // Proc macros from a proc-macro crate have a kind of virtual DefIndex. This - // function maps the index of the macro within the crate (which is also the - // index of the macro in the CrateMetadata::proc_macros array) to the - // corresponding DefIndex. - pub fn from_proc_macro_index(proc_macro_index: usize) -> DefIndex { - // DefIndex for proc macros start from FIRST_FREE_DEF_INDEX, - // because the first FIRST_FREE_DEF_INDEX indexes are reserved - // for internal use. - let def_index = DefIndex::from( - proc_macro_index.checked_add(FIRST_FREE_DEF_INDEX) - .expect("integer overflow adding `proc_macro_index`")); - assert!(def_index != CRATE_DEF_INDEX); - def_index - } - - // This function is the reverse of from_proc_macro_index() above. - pub fn to_proc_macro_index(self: DefIndex) -> usize { - self.index().checked_sub(FIRST_FREE_DEF_INDEX) - .unwrap_or_else(|| { - bug!("using local index {:?} as proc-macro index", self) - }) - } -} - impl rustc_serialize::UseSpecializedEncodable for DefIndex {} impl rustc_serialize::UseSpecializedDecodable for DefIndex {} diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index b5c760bc9a0..fa274f831b7 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -433,6 +433,7 @@ pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime LifetimeName::Static | LifetimeName::Error | LifetimeName::Implicit | + LifetimeName::ImplicitObjectLifetimeDefault | LifetimeName::Underscore => {} } } @@ -577,15 +578,15 @@ pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V, variant: &'v Variant, generics: &'v Generics, parent_item_id: HirId) { - visitor.visit_ident(variant.node.ident); - visitor.visit_id(variant.node.id); - visitor.visit_variant_data(&variant.node.data, - variant.node.ident.name, + visitor.visit_ident(variant.ident); + visitor.visit_id(variant.id); + visitor.visit_variant_data(&variant.data, + variant.ident.name, generics, parent_item_id, variant.span); - walk_list!(visitor, visit_anon_const, &variant.node.disr_expr); - walk_list!(visitor, visit_attribute, &variant.node.attrs); + walk_list!(visitor, visit_anon_const, &variant.disr_expr); + walk_list!(visitor, visit_attribute, &variant.attrs); } pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) { @@ -704,11 +705,12 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) { PatKind::Struct(ref qpath, ref fields, _) => { visitor.visit_qpath(qpath, pattern.hir_id, pattern.span); for field in fields { - visitor.visit_id(field.node.hir_id); - visitor.visit_ident(field.node.ident); - visitor.visit_pat(&field.node.pat) + visitor.visit_id(field.hir_id); + visitor.visit_ident(field.ident); + visitor.visit_pat(&field.pat) } } + PatKind::Or(ref pats) => walk_list!(visitor, visit_pat, pats), PatKind::Tuple(ref tuple_elements, _) => { walk_list!(visitor, visit_pat, tuple_elements); } diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index fe69c9e6346..7ec32106137 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -67,12 +67,12 @@ use syntax::errors; use syntax::ext::base::SpecialDerives; use syntax::ext::hygiene::ExpnId; use syntax::print::pprust; -use syntax::source_map::{respan, ExpnInfo, ExpnKind, DesugaringKind, Spanned}; +use syntax::source_map::{respan, ExpnData, ExpnKind, DesugaringKind, Spanned}; use syntax::symbol::{kw, sym, Symbol}; use syntax::tokenstream::{TokenStream, TokenTree}; use syntax::parse::token::{self, Token}; use syntax::visit::{self, Visitor}; -use syntax_pos::{DUMMY_SP, Span}; +use syntax_pos::Span; const HIR_ID_COUNTER_LOCKED: u32 = 0xFFFFFFFF; @@ -136,7 +136,10 @@ pub struct LoweringContext<'a> { /// When `is_collectin_in_band_lifetimes` is true, each lifetime is checked /// against this list to see if it is already in-scope, or if a definition /// needs to be created for it. - in_scope_lifetimes: Vec<Ident>, + /// + /// We always store a `modern()` version of the param-name in this + /// vector. + in_scope_lifetimes: Vec<ParamName>, current_module: NodeId, @@ -319,7 +322,7 @@ enum ParenthesizedGenericArgs { /// `resolve_lifetime` module. Often we "fallthrough" to that code by generating /// an "elided" or "underscore" lifetime name. In the future, we probably want to move /// everything into HIR lowering. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] enum AnonymousLifetimeMode { /// For **Modern** cases, create a new anonymous region parameter /// and reference that. @@ -337,49 +340,6 @@ enum AnonymousLifetimeMode { /// Pass responsibility to `resolve_lifetime` code for all cases. PassThrough, - - /// Used in the return types of `async fn` where there exists - /// exactly one argument-position elided lifetime. - /// - /// In `async fn`, we lower the arguments types using the `CreateParameter` - /// mode, meaning that non-`dyn` elided lifetimes are assigned a fresh name. - /// If any corresponding elided lifetimes appear in the output, we need to - /// replace them with references to the fresh name assigned to the corresponding - /// elided lifetime in the arguments. - /// - /// For **Modern cases**, replace the anonymous parameter with a - /// reference to a specific freshly-named lifetime that was - /// introduced in argument - /// - /// For **Dyn Bound** cases, pass responsibility to - /// `resole_lifetime` code. - Replace(LtReplacement), -} - -/// The type of elided lifetime replacement to perform on `async fn` return types. -#[derive(Copy, Clone)] -enum LtReplacement { - /// Fresh name introduced by the single non-dyn elided lifetime - /// in the arguments of the async fn. - Some(ParamName), - - /// There is no single non-dyn elided lifetime because no lifetimes - /// appeared in the arguments. - NoLifetimes, - - /// There is no single non-dyn elided lifetime because multiple - /// lifetimes appeared in the arguments. - MultipleLifetimes, -} - -/// Calculates the `LtReplacement` to use for elided lifetimes in the return -/// type based on the fresh elided lifetimes introduced in argument position. -fn get_elided_lt_replacement(arg_position_lifetimes: &[(Span, ParamName)]) -> LtReplacement { - match arg_position_lifetimes { - [] => LtReplacement::NoLifetimes, - [(_span, param)] => LtReplacement::Some(*param), - _ => LtReplacement::MultipleLifetimes, - } } struct ImplTraitTypeIdVisitor<'a> { ids: &'a mut SmallVec<[NodeId; 1]> } @@ -744,10 +704,9 @@ impl<'a> LoweringContext<'a> { span: Span, allow_internal_unstable: Option<Lrc<[Symbol]>>, ) -> Span { - span.fresh_expansion(ExpnId::root(), ExpnInfo { - def_site: span, + span.fresh_expansion(ExpnData { allow_internal_unstable, - ..ExpnInfo::default(ExpnKind::Desugaring(reason), span, self.sess.edition()) + ..ExpnData::default(ExpnKind::Desugaring(reason), span, self.sess.edition()) }) } @@ -756,10 +715,16 @@ impl<'a> LoweringContext<'a> { anonymous_lifetime_mode: AnonymousLifetimeMode, op: impl FnOnce(&mut Self) -> R, ) -> R { + debug!( + "with_anonymous_lifetime_mode(anonymous_lifetime_mode={:?})", + anonymous_lifetime_mode, + ); let old_anonymous_lifetime_mode = self.anonymous_lifetime_mode; self.anonymous_lifetime_mode = anonymous_lifetime_mode; let result = op(self); self.anonymous_lifetime_mode = old_anonymous_lifetime_mode; + debug!("with_anonymous_lifetime_mode: restoring anonymous_lifetime_mode={:?}", + old_anonymous_lifetime_mode); result } @@ -865,7 +830,7 @@ impl<'a> LoweringContext<'a> { return; } - if self.in_scope_lifetimes.contains(&ident.modern()) { + if self.in_scope_lifetimes.contains(&ParamName::Plain(ident.modern())) { return; } @@ -899,7 +864,7 @@ impl<'a> LoweringContext<'a> { { let old_len = self.in_scope_lifetimes.len(); let lt_def_names = params.iter().filter_map(|param| match param.kind { - GenericParamKind::Lifetime { .. } => Some(param.ident.modern()), + GenericParamKind::Lifetime { .. } => Some(ParamName::Plain(param.ident.modern())), _ => None, }); self.in_scope_lifetimes.extend(lt_def_names); @@ -1074,13 +1039,14 @@ impl<'a> LoweringContext<'a> { /// ``` /// /// returns a `hir::TypeBinding` representing `Item`. - fn lower_assoc_ty_constraint(&mut self, - c: &AssocTyConstraint, - itctx: ImplTraitContext<'_>) - -> hir::TypeBinding { - debug!("lower_assoc_ty_constraint(constraint={:?}, itctx={:?})", c, itctx); + fn lower_assoc_ty_constraint( + &mut self, + constraint: &AssocTyConstraint, + itctx: ImplTraitContext<'_>, + ) -> hir::TypeBinding { + debug!("lower_assoc_ty_constraint(constraint={:?}, itctx={:?})", constraint, itctx); - let kind = match c.kind { + let kind = match constraint.kind { AssocTyConstraintKind::Equality { ref ty } => hir::TypeBindingKind::Equality { ty: self.lower_ty(ty, itctx) }, @@ -1135,7 +1101,7 @@ impl<'a> LoweringContext<'a> { impl_trait_node_id, DefPathData::ImplTrait, ExpnId::root(), - DUMMY_SP + constraint.span, ); self.with_dyn_type_scope(false, |this| { @@ -1143,7 +1109,7 @@ impl<'a> LoweringContext<'a> { &Ty { id: this.sess.next_node_id(), node: TyKind::ImplTrait(impl_trait_node_id, bounds.clone()), - span: DUMMY_SP, + span: constraint.span, }, itctx, ); @@ -1165,10 +1131,10 @@ impl<'a> LoweringContext<'a> { }; hir::TypeBinding { - hir_id: self.lower_node_id(c.id), - ident: c.ident, + hir_id: self.lower_node_id(constraint.id), + ident: constraint.ident, kind, - span: c.span, + span: constraint.span, } } @@ -1264,7 +1230,7 @@ impl<'a> LoweringContext<'a> { P(hir::Path { res, segments: hir_vec![hir::PathSegment::from_ident( - Ident::with_empty_ctxt(kw::SelfUpper) + Ident::with_dummy_span(kw::SelfUpper) )], span: t.span, }), @@ -1396,6 +1362,13 @@ impl<'a> LoweringContext<'a> { opaque_ty_node_id: NodeId, lower_bounds: impl FnOnce(&mut LoweringContext<'_>) -> hir::GenericBounds, ) -> hir::TyKind { + debug!( + "lower_opaque_impl_trait(fn_def_id={:?}, opaque_ty_node_id={:?}, span={:?})", + fn_def_id, + opaque_ty_node_id, + span, + ); + // Make sure we know that some funky desugaring has been going on here. // This is a first: there is code in other places like for loop // desugaring that explicitly states that we don't want to track that. @@ -1423,6 +1396,14 @@ impl<'a> LoweringContext<'a> { &hir_bounds, ); + debug!( + "lower_opaque_impl_trait: lifetimes={:#?}", lifetimes, + ); + + debug!( + "lower_opaque_impl_trait: lifetime_defs={:#?}", lifetime_defs, + ); + self.with_hir_id_owner(opaque_ty_node_id, |lctx| { let opaque_ty_item = hir::OpaqueTy { generics: hir::Generics { @@ -1438,7 +1419,7 @@ impl<'a> LoweringContext<'a> { origin: hir::OpaqueTyOrigin::FnReturn, }; - trace!("exist ty from impl trait def-index: {:#?}", opaque_ty_def_index); + trace!("lower_opaque_impl_trait: {:#?}", opaque_ty_def_index); let opaque_ty_id = lctx.generate_opaque_type( opaque_ty_node_id, opaque_ty_item, @@ -1486,6 +1467,13 @@ impl<'a> LoweringContext<'a> { parent_index: DefIndex, bounds: &hir::GenericBounds, ) -> (HirVec<hir::GenericArg>, HirVec<hir::GenericParam>) { + debug!( + "lifetimes_from_impl_trait_bounds(opaque_ty_id={:?}, \ + parent_index={:?}, \ + bounds={:#?})", + opaque_ty_id, parent_index, bounds, + ); + // This visitor walks over `impl Trait` bounds and creates defs for all lifetimes that // appear in the bounds, excluding lifetimes that are created within the bounds. // E.g., `'a`, `'b`, but not `'c` in `impl for<'c> SomeTrait<'a, 'b, 'c>`. @@ -1573,6 +1561,11 @@ impl<'a> LoweringContext<'a> { } } hir::LifetimeName::Param(_) => lifetime.name, + + // Refers to some other lifetime that is "in + // scope" within the type. + hir::LifetimeName::ImplicitObjectLifetimeDefault => return, + hir::LifetimeName::Error | hir::LifetimeName::Static => return, }; @@ -1598,7 +1591,7 @@ impl<'a> LoweringContext<'a> { let (name, kind) = match name { hir::LifetimeName::Underscore => ( - hir::ParamName::Plain(Ident::with_empty_ctxt(kw::UnderscoreLifetime)), + hir::ParamName::Plain(Ident::with_dummy_span(kw::UnderscoreLifetime)), hir::LifetimeParamKind::Elided, ), hir::LifetimeName::Param(param_name) => ( @@ -1953,8 +1946,7 @@ impl<'a> LoweringContext<'a> { err.emit(); } AnonymousLifetimeMode::PassThrough | - AnonymousLifetimeMode::ReportError | - AnonymousLifetimeMode::Replace(_) => { + AnonymousLifetimeMode::ReportError => { self.sess.buffer_lint_with_diagnostic( ELIDED_LIFETIMES_IN_PATHS, CRATE_NODE_ID, @@ -2043,7 +2035,7 @@ impl<'a> LoweringContext<'a> { bindings: hir_vec![ hir::TypeBinding { hir_id: this.next_id(), - ident: Ident::with_empty_ctxt(FN_OUTPUT_NAME), + ident: Ident::with_dummy_span(FN_OUTPUT_NAME), kind: hir::TypeBindingKind::Equality { ty: output .as_ref() @@ -2141,7 +2133,6 @@ impl<'a> LoweringContext<'a> { // Remember how many lifetimes were already around so that we can // only look at the lifetime parameters introduced by the arguments. - let lifetime_count_before_args = self.lifetimes_to_define.len(); let inputs = self.with_anonymous_lifetime_mode(lt_mode, |this| { decl.inputs .iter() @@ -2156,16 +2147,10 @@ impl<'a> LoweringContext<'a> { }); let output = if let Some(ret_id) = make_ret_async { - // Calculate the `LtReplacement` to use for any return-position elided - // lifetimes based on the elided lifetime parameters introduced in the args. - let lt_replacement = get_elided_lt_replacement( - &self.lifetimes_to_define[lifetime_count_before_args..] - ); self.lower_async_fn_ret_ty( &decl.output, in_band_ty_params.expect("`make_ret_async` but no `fn_def_id`").0, ret_id, - lt_replacement, ) } else { match decl.output { @@ -2230,8 +2215,15 @@ impl<'a> LoweringContext<'a> { output: &FunctionRetTy, fn_def_id: DefId, opaque_ty_node_id: NodeId, - elided_lt_replacement: LtReplacement, ) -> hir::FunctionRetTy { + debug!( + "lower_async_fn_ret_ty(\ + output={:?}, \ + fn_def_id={:?}, \ + opaque_ty_node_id={:?})", + output, fn_def_id, opaque_ty_node_id, + ); + let span = output.span(); let opaque_ty_span = self.mark_span_with_reason( @@ -2248,9 +2240,65 @@ impl<'a> LoweringContext<'a> { self.allocate_hir_id_counter(opaque_ty_node_id); + // When we create the opaque type for this async fn, it is going to have + // to capture all the lifetimes involved in the signature (including in the + // return type). This is done by introducing lifetime parameters for: + // + // - all the explicitly declared lifetimes from the impl and function itself; + // - all the elided lifetimes in the fn arguments; + // - all the elided lifetimes in the return type. + // + // So for example in this snippet: + // + // ```rust + // impl<'a> Foo<'a> { + // async fn bar<'b>(&self, x: &'b Vec<f64>, y: &str) -> &u32 { + // // ^ '0 ^ '1 ^ '2 + // // elided lifetimes used below + // } + // } + // ``` + // + // we would create an opaque type like: + // + // ``` + // type Bar<'a, 'b, '0, '1, '2> = impl Future<Output = &'2 u32>; + // ``` + // + // and we would then desugar `bar` to the equivalent of: + // + // ```rust + // impl<'a> Foo<'a> { + // fn bar<'b, '0, '1>(&'0 self, x: &'b Vec<f64>, y: &'1 str) -> Bar<'a, 'b, '0, '1, '_> + // } + // ``` + // + // Note that the final parameter to `Bar` is `'_`, not `'2` -- + // this is because the elided lifetimes from the return type + // should be figured out using the ordinary elision rules, and + // this desugaring achieves that. + // + // The variable `input_lifetimes_count` tracks the number of + // lifetime parameters to the opaque type *not counting* those + // lifetimes elided in the return type. This includes those + // that are explicitly declared (`in_scope_lifetimes`) and + // those elided lifetimes we found in the arguments (current + // content of `lifetimes_to_define`). Next, we will process + // the return type, which will cause `lifetimes_to_define` to + // grow. + let input_lifetimes_count = self.in_scope_lifetimes.len() + self.lifetimes_to_define.len(); + let (opaque_ty_id, lifetime_params) = self.with_hir_id_owner(opaque_ty_node_id, |this| { + // We have to be careful to get elision right here. The + // idea is that we create a lifetime parameter for each + // lifetime in the return type. So, given a return type + // like `async fn foo(..) -> &[&u32]`, we lower to `impl + // Future<Output = &'1 [ &'2 u32 ]>`. + // + // Then, we will create `fn foo(..) -> Foo<'_, '_>`, and + // hence the elision takes place at the fn site. let future_bound = this.with_anonymous_lifetime_mode( - AnonymousLifetimeMode::Replace(elided_lt_replacement), + AnonymousLifetimeMode::CreateParameter, |this| this.lower_async_fn_output_type_to_future_bound( output, fn_def_id, @@ -2258,6 +2306,8 @@ impl<'a> LoweringContext<'a> { ), ); + debug!("lower_async_fn_ret_ty: future_bound={:#?}", future_bound); + // Calculate all the lifetimes that should be captured // by the opaque type. This should include all in-scope // lifetime parameters, including those defined in-band. @@ -2267,10 +2317,14 @@ impl<'a> LoweringContext<'a> { let lifetime_params: Vec<(Span, ParamName)> = this.in_scope_lifetimes .iter().cloned() - .map(|ident| (ident.span, ParamName::Plain(ident))) + .map(|name| (name.ident().span, name)) .chain(this.lifetimes_to_define.iter().cloned()) .collect(); + debug!("lower_async_fn_ret_ty: in_scope_lifetimes={:#?}", this.in_scope_lifetimes); + debug!("lower_async_fn_ret_ty: lifetimes_to_define={:#?}", this.lifetimes_to_define); + debug!("lower_async_fn_ret_ty: lifetime_params={:#?}", lifetime_params); + let generic_params = lifetime_params .iter().cloned() @@ -2304,19 +2358,52 @@ impl<'a> LoweringContext<'a> { (opaque_ty_id, lifetime_params) }); - let generic_args = - lifetime_params - .iter().cloned() - .map(|(span, hir_name)| { - GenericArg::Lifetime(hir::Lifetime { - hir_id: self.next_id(), - span, - name: hir::LifetimeName::Param(hir_name), - }) + // As documented above on the variable + // `input_lifetimes_count`, we need to create the lifetime + // arguments to our opaque type. Continuing with our example, + // we're creating the type arguments for the return type: + // + // ``` + // Bar<'a, 'b, '0, '1, '_> + // ``` + // + // For the "input" lifetime parameters, we wish to create + // references to the parameters themselves, including the + // "implicit" ones created from parameter types (`'a`, `'b`, + // '`0`, `'1`). + // + // For the "output" lifetime parameters, we just want to + // generate `'_`. + let mut generic_args: Vec<_> = + lifetime_params[..input_lifetimes_count] + .iter() + .map(|&(span, hir_name)| { + // Input lifetime like `'a` or `'1`: + GenericArg::Lifetime(hir::Lifetime { + hir_id: self.next_id(), + span, + name: hir::LifetimeName::Param(hir_name), }) - .collect(); + }) + .collect(); + generic_args.extend( + lifetime_params[input_lifetimes_count..] + .iter() + .map(|&(span, _)| { + // Output lifetime like `'_`. + GenericArg::Lifetime(hir::Lifetime { + hir_id: self.next_id(), + span, + name: hir::LifetimeName::Implicit, + }) + }) + ); - let opaque_ty_ref = hir::TyKind::Def(hir::ItemId { id: opaque_ty_id }, generic_args); + // Create the `Foo<...>` refernece itself. Note that the `type + // Foo = impl Trait` is, internally, created as a child of the + // async fn, so the *type parameters* are inherited. It's + // only the lifetime parameters that we must supply. + let opaque_ty_ref = hir::TyKind::Def(hir::ItemId { id: opaque_ty_id }, generic_args.into()); hir::FunctionRetTy::Return(P(hir::Ty { node: opaque_ty_ref, @@ -2350,7 +2437,7 @@ impl<'a> LoweringContext<'a> { let future_params = P(hir::GenericArgs { args: hir_vec![], bindings: hir_vec![hir::TypeBinding { - ident: Ident::with_empty_ctxt(FN_OUTPUT_NAME), + ident: Ident::with_dummy_span(FN_OUTPUT_NAME), kind: hir::TypeBindingKind::Equality { ty: output_ty, }, @@ -2412,11 +2499,6 @@ impl<'a> LoweringContext<'a> { } AnonymousLifetimeMode::ReportError => self.new_error_lifetime(Some(l.id), span), - - AnonymousLifetimeMode::Replace(replacement) => { - let hir_id = self.lower_node_id(l.id); - self.replace_elided_lifetime(hir_id, span, replacement) - } }, ident => { self.maybe_collect_in_band_lifetime(ident); @@ -2439,39 +2521,6 @@ impl<'a> LoweringContext<'a> { } } - /// Replace a return-position elided lifetime with the elided lifetime - /// from the arguments. - fn replace_elided_lifetime( - &mut self, - hir_id: hir::HirId, - span: Span, - replacement: LtReplacement, - ) -> hir::Lifetime { - let multiple_or_none = match replacement { - LtReplacement::Some(name) => { - return hir::Lifetime { - hir_id, - span, - name: hir::LifetimeName::Param(name), - }; - } - LtReplacement::MultipleLifetimes => "multiple", - LtReplacement::NoLifetimes => "none", - }; - - let mut err = crate::middle::resolve_lifetime::report_missing_lifetime_specifiers( - self.sess, - span, - 1, - ); - err.note(&format!( - "return-position elided lifetimes require exactly one \ - input-position elided lifetime, found {}.", multiple_or_none)); - err.emit(); - - hir::Lifetime { hir_id, span, name: hir::LifetimeName::Error } - } - fn lower_generic_params( &mut self, params: &[GenericParam], @@ -2507,6 +2556,12 @@ impl<'a> LoweringContext<'a> { hir::LifetimeName::Implicit | hir::LifetimeName::Underscore | hir::LifetimeName::Static => hir::ParamName::Plain(lt.name.ident()), + hir::LifetimeName::ImplicitObjectLifetimeDefault => { + span_bug!( + param.ident.span, + "object-lifetime-default should not occur here", + ); + } hir::LifetimeName::Error => ParamName::Error, }; @@ -2519,15 +2574,6 @@ impl<'a> LoweringContext<'a> { (param_name, kind) } GenericParamKind::Type { ref default, .. } => { - // Don't expose `Self` (recovered "keyword used as ident" parse error). - // `rustc::ty` expects `Self` to be only used for a trait's `Self`. - // Instead, use `gensym("Self")` to create a distinct name that looks the same. - let ident = if param.ident.name == kw::SelfUpper { - param.ident.gensym() - } else { - param.ident - }; - let add_bounds = add_bounds.get(¶m.id).map_or(&[][..], |x| &x); if !add_bounds.is_empty() { let params = self.lower_param_bounds(add_bounds, itctx.reborrow()).into_iter(); @@ -2546,7 +2592,7 @@ impl<'a> LoweringContext<'a> { .next(), }; - (hir::ParamName::Plain(ident), kind) + (hir::ParamName::Plain(param.ident), kind) } GenericParamKind::Const { ref ty } => { (hir::ParamName::Plain(param.ident), hir::GenericParamKind::Const { @@ -2664,6 +2710,9 @@ impl<'a> LoweringContext<'a> { let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple struct"); hir::PatKind::TupleStruct(qpath, pats, ddpos) } + PatKind::Or(ref pats) => { + hir::PatKind::Or(pats.iter().map(|x| self.lower_pat(x)).collect()) + } PatKind::Path(ref qself, ref path) => { let qpath = self.lower_qpath( p.id, @@ -2685,16 +2734,12 @@ impl<'a> LoweringContext<'a> { let fs = fields .iter() - .map(|f| { - Spanned { - span: f.span, - node: hir::FieldPat { - hir_id: self.next_id(), - ident: f.node.ident, - pat: self.lower_pat(&f.node.pat), - is_shorthand: f.node.is_shorthand, - }, - } + .map(|f| hir::FieldPat { + hir_id: self.next_id(), + ident: f.ident, + pat: self.lower_pat(&f.pat), + is_shorthand: f.is_shorthand, + span: f.span, }) .collect(); hir::PatKind::Struct(qpath, fs, etc) @@ -3174,10 +3219,6 @@ impl<'a> LoweringContext<'a> { AnonymousLifetimeMode::ReportError => self.new_error_lifetime(None, span), AnonymousLifetimeMode::PassThrough => self.new_implicit_lifetime(span), - - AnonymousLifetimeMode::Replace(replacement) => { - self.new_replacement_lifetime(replacement, span) - } } } @@ -3231,10 +3272,6 @@ impl<'a> LoweringContext<'a> { // This is the normal case. AnonymousLifetimeMode::PassThrough => self.new_implicit_lifetime(span), - AnonymousLifetimeMode::Replace(replacement) => { - self.new_replacement_lifetime(replacement, span) - } - AnonymousLifetimeMode::ReportError => self.new_error_lifetime(None, span), } } @@ -3266,23 +3303,15 @@ impl<'a> LoweringContext<'a> { // This is the normal case. AnonymousLifetimeMode::PassThrough => {} - - // We don't need to do any replacement here as this lifetime - // doesn't refer to an elided lifetime elsewhere in the function - // signature. - AnonymousLifetimeMode::Replace(_) => {} } - self.new_implicit_lifetime(span) - } - - fn new_replacement_lifetime( - &mut self, - replacement: LtReplacement, - span: Span, - ) -> hir::Lifetime { - let hir_id = self.next_id(); - self.replace_elided_lifetime(hir_id, span, replacement) + let r = hir::Lifetime { + hir_id: self.next_id(), + span, + name: hir::LifetimeName::ImplicitObjectLifetimeDefault, + }; + debug!("elided_dyn_bound: r={:?}", r); + r } fn new_implicit_lifetime(&mut self, span: Span) -> hir::Lifetime { diff --git a/src/librustc/hir/lowering/expr.rs b/src/librustc/hir/lowering/expr.rs index d273006fbe0..ff0c44a2387 100644 --- a/src/librustc/hir/lowering/expr.rs +++ b/src/librustc/hir/lowering/expr.rs @@ -552,7 +552,7 @@ impl LoweringContext<'_> { // let mut pinned = <expr>; let expr = P(self.lower_expr(expr)); - let pinned_ident = Ident::with_empty_ctxt(sym::pinned); + let pinned_ident = Ident::with_dummy_span(sym::pinned); let (pinned_pat, pinned_pat_hid) = self.pat_ident_binding_mode( span, pinned_ident, @@ -593,7 +593,7 @@ impl LoweringContext<'_> { let loop_node_id = self.sess.next_node_id(); let loop_hir_id = self.lower_node_id(loop_node_id); let ready_arm = { - let x_ident = Ident::with_empty_ctxt(sym::result); + let x_ident = Ident::with_dummy_span(sym::result); let (x_pat, x_pat_hid) = self.pat_ident(span, x_ident); let x_expr = P(self.expr_ident(span, x_ident, x_pat_hid)); let ready_pat = self.pat_std_enum( @@ -677,6 +677,7 @@ impl LoweringContext<'_> { let fn_decl = self.lower_fn_decl(decl, None, false, None); self.with_new_scopes(|this| { + let prev = this.current_item; this.current_item = Some(fn_decl_span); let mut generator_kind = None; let body_id = this.lower_fn_body(decl, |this| { @@ -690,8 +691,10 @@ impl LoweringContext<'_> { generator_kind, movability, ); + let capture_clause = this.lower_capture_clause(capture_clause); + this.current_item = prev; hir::ExprKind::Closure( - this.lower_capture_clause(capture_clause), + capture_clause, fn_decl, body_id, fn_decl_span, @@ -981,7 +984,6 @@ impl LoweringContext<'_> { volatile: asm.volatile, alignstack: asm.alignstack, dialect: asm.dialect, - ctxt: asm.ctxt, }; let outputs = asm.outputs @@ -1067,9 +1069,9 @@ impl LoweringContext<'_> { ); head.span = desugared_span; - let iter = Ident::with_empty_ctxt(sym::iter); + let iter = Ident::with_dummy_span(sym::iter); - let next_ident = Ident::with_empty_ctxt(sym::__next); + let next_ident = Ident::with_dummy_span(sym::__next); let (next_pat, next_pat_hid) = self.pat_ident_binding_mode( desugared_span, next_ident, @@ -1078,7 +1080,7 @@ impl LoweringContext<'_> { // `::std::option::Option::Some(val) => __next = val` let pat_arm = { - let val_ident = Ident::with_empty_ctxt(sym::val); + let val_ident = Ident::with_dummy_span(sym::val); let (val_pat, val_pat_hid) = self.pat_ident(pat.span, val_ident); let val_expr = P(self.expr_ident(pat.span, val_ident, val_pat_hid)); let next_expr = P(self.expr_ident(pat.span, next_ident, next_pat_hid)); @@ -1244,7 +1246,7 @@ impl LoweringContext<'_> { // `Ok(val) => #[allow(unreachable_code)] val,` let ok_arm = { - let val_ident = Ident::with_empty_ctxt(sym::val); + let val_ident = Ident::with_dummy_span(sym::val); let (val_pat, val_pat_nid) = self.pat_ident(span, val_ident); let val_expr = P(self.expr_ident_with_attrs( span, @@ -1260,7 +1262,7 @@ impl LoweringContext<'_> { // `Err(err) => #[allow(unreachable_code)] // return Try::from_error(From::from(err)),` let err_arm = { - let err_ident = Ident::with_empty_ctxt(sym::err); + let err_ident = Ident::with_dummy_span(sym::err); let (err_local, err_local_nid) = self.pat_ident(try_span, err_ident); let from_expr = { let from_path = &[sym::convert, sym::From, sym::from]; diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs index 6b717e75199..4f9a9ed5673 100644 --- a/src/librustc/hir/lowering/item.rs +++ b/src/librustc/hir/lowering/item.rs @@ -60,10 +60,12 @@ impl<'tcx, 'interner> Visitor<'tcx> for ItemLowerer<'tcx, 'interner> { fn visit_item(&mut self, item: &'tcx Item) { let mut item_hir_id = None; self.lctx.with_hir_id_owner(item.id, |lctx| { - if let Some(hir_item) = lctx.lower_item(item) { - item_hir_id = Some(hir_item.hir_id); - lctx.insert_item(hir_item); - } + lctx.without_in_scope_lifetime_defs(|lctx| { + if let Some(hir_item) = lctx.lower_item(item) { + item_hir_id = Some(hir_item.hir_id); + lctx.insert_item(hir_item); + } + }) }); if let Some(hir_id) = item_hir_id { @@ -123,7 +125,7 @@ impl LoweringContext<'_> { _ => &[], }; let lt_def_names = parent_generics.iter().filter_map(|param| match param.kind { - hir::GenericParamKind::Lifetime { .. } => Some(param.name.ident().modern()), + hir::GenericParamKind::Lifetime { .. } => Some(param.name.modern()), _ => None, }); self.in_scope_lifetimes.extend(lt_def_names); @@ -134,6 +136,28 @@ impl LoweringContext<'_> { res } + // Clears (and restores) the `in_scope_lifetimes` field. Used when + // visiting nested items, which never inherit in-scope lifetimes + // from their surrounding environment. + fn without_in_scope_lifetime_defs<T>( + &mut self, + f: impl FnOnce(&mut LoweringContext<'_>) -> T, + ) -> T { + let old_in_scope_lifetimes = std::mem::replace(&mut self.in_scope_lifetimes, vec![]); + + // this vector is only used when walking over impl headers, + // input types, and the like, and should not be non-empty in + // between items + assert!(self.lifetimes_to_define.is_empty()); + + let res = f(self); + + assert!(self.in_scope_lifetimes.is_empty()); + self.in_scope_lifetimes = old_in_scope_lifetimes; + + res + } + pub(super) fn lower_mod(&mut self, m: &Mod) -> hir::Mod { hir::Mod { inner: m.inner, @@ -726,21 +750,16 @@ impl LoweringContext<'_> { } fn lower_global_asm(&mut self, ga: &GlobalAsm) -> P<hir::GlobalAsm> { - P(hir::GlobalAsm { - asm: ga.asm, - ctxt: ga.ctxt, - }) + P(hir::GlobalAsm { asm: ga.asm }) } fn lower_variant(&mut self, v: &Variant) -> hir::Variant { - Spanned { - node: hir::VariantKind { - ident: v.node.ident, - id: self.lower_node_id(v.node.id), - attrs: self.lower_attrs(&v.node.attrs), - data: self.lower_variant_data(&v.node.data), - disr_expr: v.node.disr_expr.as_ref().map(|e| self.lower_anon_const(e)), - }, + hir::Variant { + attrs: self.lower_attrs(&v.attrs), + data: self.lower_variant_data(&v.data), + disr_expr: v.disr_expr.as_ref().map(|e| self.lower_anon_const(e)), + id: self.lower_node_id(v.id), + ident: v.ident, span: v.span, } } diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index b6807f7d3bb..effe2c0cc6a 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -544,11 +544,11 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } fn visit_variant(&mut self, v: &'hir Variant, g: &'hir Generics, item_id: HirId) { - self.insert(v.span, v.node.id, Node::Variant(v)); - self.with_parent(v.node.id, |this| { + self.insert(v.span, v.id, Node::Variant(v)); + self.with_parent(v.id, |this| { // Register the constructor of this variant. - if let Some(ctor_hir_id) = v.node.data.ctor_hir_id() { - this.insert(v.span, ctor_hir_id, Node::Ctor(&v.node.data)); + if let Some(ctor_hir_id) = v.data.ctor_hir_id() { + this.insert(v.span, ctor_hir_id, Node::Ctor(&v.data)); } intravisit::walk_variant(this, v, g, item_id); }); diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index 2964b130ddd..d725afa4052 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -74,7 +74,7 @@ impl<'a> DefCollector<'a> { }) } - fn visit_macro_invoc(&mut self, id: NodeId) { + pub fn visit_macro_invoc(&mut self, id: NodeId) { self.definitions.set_invocation_parent(id.placeholder_to_expn_id(), self.parent_def); } } @@ -155,11 +155,11 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { } fn visit_variant(&mut self, v: &'a Variant, g: &'a Generics, item_id: NodeId) { - let def = self.create_def(v.node.id, - DefPathData::TypeNs(v.node.ident.as_interned_str()), + let def = self.create_def(v.id, + DefPathData::TypeNs(v.ident.as_interned_str()), v.span); self.with_parent(def, |this| { - if let Some(ctor_hir_id) = v.node.data.ctor_id() { + if let Some(ctor_hir_id) = v.data.ctor_id() { this.create_def(ctor_hir_id, DefPathData::Ctor, v.span); } visit::walk_variant(this, v, g, item_id) diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index 8ee8c6d0e89..6dc3c7038f5 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -411,10 +411,6 @@ impl Definitions { } /// Adds a root definition (no parent) and a few other reserved definitions. - /// - /// After the initial definitions are created the first `FIRST_FREE_DEF_INDEX` indexes - /// are taken, so the "user" indexes will be allocated starting with `FIRST_FREE_DEF_INDEX` - /// in ascending order. pub fn create_root_def(&mut self, crate_name: &str, crate_disambiguator: CrateDisambiguator) @@ -589,19 +585,6 @@ impl DefPathData { } } -/// Evaluates to the number of tokens passed to it. -/// -/// Logarithmic counting: every one or two recursive expansions, the number of -/// tokens to count is divided by two, instead of being reduced by one. -/// Therefore, the recursion depth is the binary logarithm of the number of -/// tokens to count, and the expanded tree is likewise very small. -macro_rules! count { - () => (0usize); - ($one:tt) => (1usize); - ($($pairs:tt $_p:tt)*) => (count!($($pairs)*) << 1usize); - ($odd:tt $($rest:tt)*) => (count!($($rest)*) | 1usize); -} - // We define the GlobalMetaDataKind enum with this macro because we want to // make sure that we exhaustively iterate over all variants when registering // the corresponding DefIndices in the DefTable. @@ -614,8 +597,6 @@ macro_rules! define_global_metadata_kind { $($variant),* } - pub const FIRST_FREE_DEF_INDEX: usize = 1 + count!($($variant)*); - impl GlobalMetaDataKind { fn allocate_def_indices(definitions: &mut Definitions) { $({ diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index b85738dd29a..7292428ec37 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -649,12 +649,34 @@ impl<'hir> Map<'hir> { } } - pub fn is_const_scope(&self, hir_id: HirId) -> bool { - self.walk_parent_nodes(hir_id, |node| match *node { - Node::Item(Item { node: ItemKind::Const(_, _), .. }) => true, - Node::Item(Item { node: ItemKind::Fn(_, header, _, _), .. }) => header.is_const(), + /// Whether the expression pointed at by `hir_id` belongs to a `const` evaluation context. + /// Used exclusively for diagnostics, to avoid suggestion function calls. + pub fn is_const_context(&self, hir_id: HirId) -> bool { + let parent_id = self.get_parent_item(hir_id); + match self.get(parent_id) { + Node::Item(&Item { + node: ItemKind::Const(..), + .. + }) + | Node::TraitItem(&TraitItem { + node: TraitItemKind::Const(..), + .. + }) + | Node::ImplItem(&ImplItem { + node: ImplItemKind::Const(..), + .. + }) + | Node::AnonConst(_) + | Node::Item(&Item { + node: ItemKind::Static(..), + .. + }) => true, + Node::Item(&Item { + node: ItemKind::Fn(_, header, ..), + .. + }) => header.constness == Constness::Const, _ => false, - }, |_| false).map(|id| id != CRATE_HIR_ID).unwrap_or(false) + } } /// If there is some error when walking the parents (e.g., a node does not @@ -885,7 +907,7 @@ impl<'hir> Map<'hir> { _ => bug!("struct ID bound to non-struct {}", self.node_to_string(id)) } } - Some(Node::Variant(variant)) => &variant.node.data, + Some(Node::Variant(variant)) => &variant.data, Some(Node::Ctor(data)) => data, _ => bug!("expected struct or variant, found {}", self.node_to_string(id)) } @@ -918,7 +940,7 @@ impl<'hir> Map<'hir> { Node::ForeignItem(fi) => fi.ident.name, Node::ImplItem(ii) => ii.ident.name, Node::TraitItem(ti) => ti.ident.name, - Node::Variant(v) => v.node.ident.name, + Node::Variant(v) => v.ident.name, Node::Field(f) => f.ident.name, Node::Lifetime(lt) => lt.name.ident().name, Node::GenericParam(param) => param.name.ident().name, @@ -939,7 +961,7 @@ impl<'hir> Map<'hir> { Some(Node::ForeignItem(fi)) => Some(&fi.attrs[..]), Some(Node::TraitItem(ref ti)) => Some(&ti.attrs[..]), Some(Node::ImplItem(ref ii)) => Some(&ii.attrs[..]), - Some(Node::Variant(ref v)) => Some(&v.node.attrs[..]), + Some(Node::Variant(ref v)) => Some(&v.attrs[..]), Some(Node::Field(ref f)) => Some(&f.attrs[..]), Some(Node::Expr(ref e)) => Some(&*e.attrs), Some(Node::Stmt(ref s)) => Some(s.node.attrs()), @@ -1133,7 +1155,7 @@ impl<T:Named> Named for Spanned<T> { fn name(&self) -> Name { self.node.name() } impl Named for Item { fn name(&self) -> Name { self.ident.name } } impl Named for ForeignItem { fn name(&self) -> Name { self.ident.name } } -impl Named for VariantKind { fn name(&self) -> Name { self.ident.name } } +impl Named for Variant { fn name(&self) -> Name { self.ident.name } } impl Named for StructField { fn name(&self) -> Name { self.ident.name } } impl Named for TraitItem { fn name(&self) -> Name { self.ident.name } } impl Named for ImplItem { fn name(&self) -> Name { self.ident.name } } @@ -1310,7 +1332,7 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId, include_id: bool) -> String { } Some(Node::Variant(ref variant)) => { format!("variant {} in {}{}", - variant.node.ident, + variant.ident, path_str(), id_str) } Some(Node::Field(ref field)) => { diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 3d049fe4ccd..98304818852 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -23,7 +23,6 @@ use rustc_target::spec::abi::Abi; use syntax::ast::{self, CrateSugar, Ident, Name, NodeId, AsmDialect}; use syntax::ast::{Attribute, Label, LitKind, StrStyle, FloatTy, IntTy, UintTy}; use syntax::attr::{InlineAttr, OptimizeAttr}; -use syntax::ext::hygiene::SyntaxContext; use syntax::symbol::{Symbol, kw}; use syntax::tokenstream::TokenStream; use syntax::util::parser::ExprPrecedence; @@ -202,7 +201,7 @@ impl ParamName { match *self { ParamName::Plain(ident) => ident, ParamName::Fresh(_) | - ParamName::Error => Ident::with_empty_ctxt(kw::UnderscoreLifetime), + ParamName::Error => Ident::with_dummy_span(kw::UnderscoreLifetime), } } @@ -222,6 +221,19 @@ pub enum LifetimeName { /// User wrote nothing (e.g., the lifetime in `&u32`). Implicit, + /// Implicit lifetime in a context like `dyn Foo`. This is + /// distinguished from implicit lifetimes elsewhere because the + /// lifetime that they default to must appear elsewhere within the + /// enclosing type. This means that, in an `impl Trait` context, we + /// don't have to create a parameter for them. That is, `impl + /// Trait<Item = &u32>` expands to an opaque type like `type + /// Foo<'a> = impl Trait<Item = &'a u32>`, but `impl Trait<item = + /// dyn Bar>` expands to `type Foo = impl Trait<Item = dyn Bar + + /// 'static>`. The latter uses `ImplicitObjectLifetimeDefault` so + /// that surrounding code knows not to create a lifetime + /// parameter. + ImplicitObjectLifetimeDefault, + /// Indicates an error during lowering (usually `'_` in wrong place) /// that was already reported. Error, @@ -236,16 +248,20 @@ pub enum LifetimeName { impl LifetimeName { pub fn ident(&self) -> Ident { match *self { - LifetimeName::Implicit | LifetimeName::Error => Ident::invalid(), - LifetimeName::Underscore => Ident::with_empty_ctxt(kw::UnderscoreLifetime), - LifetimeName::Static => Ident::with_empty_ctxt(kw::StaticLifetime), + LifetimeName::ImplicitObjectLifetimeDefault + | LifetimeName::Implicit + | LifetimeName::Error => Ident::invalid(), + LifetimeName::Underscore => Ident::with_dummy_span(kw::UnderscoreLifetime), + LifetimeName::Static => Ident::with_dummy_span(kw::StaticLifetime), LifetimeName::Param(param_name) => param_name.ident(), } } pub fn is_elided(&self) -> bool { match self { - LifetimeName::Implicit | LifetimeName::Underscore => true, + LifetimeName::ImplicitObjectLifetimeDefault + | LifetimeName::Implicit + | LifetimeName::Underscore => true, // It might seem surprising that `Fresh(_)` counts as // *not* elided -- but this is because, as far as the code @@ -877,11 +893,12 @@ impl Pat { match self.node { PatKind::Binding(.., Some(ref p)) => p.walk_(it), PatKind::Struct(_, ref fields, _) => { - fields.iter().all(|field| field.node.pat.walk_(it)) + fields.iter().all(|field| field.pat.walk_(it)) } PatKind::TupleStruct(_, ref s, _) | PatKind::Tuple(ref s, _) => { s.iter().all(|p| p.walk_(it)) } + PatKind::Or(ref pats) => pats.iter().all(|p| p.walk_(it)), PatKind::Box(ref s) | PatKind::Ref(ref s, _) => { s.walk_(it) } @@ -923,6 +940,7 @@ pub struct FieldPat { /// The pattern the field is destructured to. pub pat: P<Pat>, pub is_shorthand: bool, + pub span: Span, } /// Explicit binding annotations given in the HIR for a binding. Note @@ -968,13 +986,17 @@ pub enum PatKind { /// A struct or struct variant pattern (e.g., `Variant {x, y, ..}`). /// The `bool` is `true` in the presence of a `..`. - Struct(QPath, HirVec<Spanned<FieldPat>>, bool), + Struct(QPath, HirVec<FieldPat>, bool), /// A tuple struct/variant pattern `Variant(x, y, .., z)`. /// If the `..` pattern fragment is present, then `Option<usize>` denotes its position. /// `0 <= position <= subpats.len()` TupleStruct(QPath, HirVec<P<Pat>>, Option<usize>), + /// An or-pattern `A | B | C`. + /// Invariant: `pats.len() >= 2`. + Or(HirVec<P<Pat>>), + /// A path pattern for an unit struct/variant or a (maybe-associated) constant. Path(QPath), @@ -1541,7 +1563,7 @@ pub enum ExprKind { Match(P<Expr>, HirVec<Arm>, MatchSource), /// A closure (e.g., `move |a, b, c| {a + b + c}`). /// - /// The final span is the span of the argument block `|...|`. + /// The `Span` is the argument block `|...|`. /// /// This may also be a generator literal or an `async block` as indicated by the /// `Option<GeneratorMovability>`. @@ -2003,8 +2025,6 @@ pub struct InlineAsm { pub volatile: bool, pub alignstack: bool, pub dialect: AsmDialect, - #[stable_hasher(ignore)] // This is used for error reporting - pub ctxt: SyntaxContext, } /// Represents an argument in a function header. @@ -2183,8 +2203,6 @@ pub struct ForeignMod { #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] pub struct GlobalAsm { pub asm: Symbol, - #[stable_hasher(ignore)] // This is used for error reporting - pub ctxt: SyntaxContext, } #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] @@ -2193,7 +2211,7 @@ pub struct EnumDef { } #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] -pub struct VariantKind { +pub struct Variant { /// Name of the variant. #[stable_hasher(project(name))] pub ident: Ident, @@ -2205,10 +2223,10 @@ pub struct VariantKind { pub data: VariantData, /// Explicit discriminant (e.g., `Foo = 1`). pub disr_expr: Option<AnonConst>, + /// Span + pub span: Span } -pub type Variant = Spanned<VariantKind>; - #[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable)] pub enum UseKind { /// One import, e.g., `use foo::bar` or `use foo::bar as baz`. diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 11ba5120530..632a13f9183 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -737,7 +737,7 @@ impl<'a> State<'a> { for v in variants { self.space_if_not_bol(); self.maybe_print_comment(v.span.lo()); - self.print_outer_attributes(&v.node.attrs); + self.print_outer_attributes(&v.attrs); self.ibox(INDENT_UNIT); self.print_variant(v); self.s.word(","); @@ -829,8 +829,8 @@ impl<'a> State<'a> { pub fn print_variant(&mut self, v: &hir::Variant) { self.head(""); let generics = hir::Generics::empty(); - self.print_struct(&v.node.data, &generics, v.node.ident.name, v.span, false); - if let Some(ref d) = v.node.disr_expr { + self.print_struct(&v.data, &generics, v.ident.name, v.span, false); + if let Some(ref d) = v.disr_expr { self.s.space(); self.word_space("="); self.print_anon_const(d); @@ -1457,7 +1457,7 @@ impl<'a> State<'a> { } pub fn print_name(&mut self, name: ast::Name) { - self.print_ident(ast::Ident::with_empty_ctxt(name)) + self.print_ident(ast::Ident::with_dummy_span(name)) } pub fn print_for_decl(&mut self, loc: &hir::Local, coll: &hir::Expr) { @@ -1670,14 +1670,14 @@ impl<'a> State<'a> { &fields[..], |s, f| { s.cbox(INDENT_UNIT); - if !f.node.is_shorthand { - s.print_ident(f.node.ident); + if !f.is_shorthand { + s.print_ident(f.ident); s.word_nbsp(":"); } - s.print_pat(&f.node.pat); + s.print_pat(&f.pat); s.end() }, - |f| f.node.pat.span); + |f| f.pat.span); if etc { if !fields.is_empty() { self.word_space(","); @@ -1687,6 +1687,9 @@ impl<'a> State<'a> { self.s.space(); self.s.word("}"); } + PatKind::Or(ref pats) => { + self.strsep("|", true, Inconsistent, &pats[..], |s, p| s.print_pat(&p)); + } PatKind::Tuple(ref elts, ddpos) => { self.popen(); if let Some(ddpos) = ddpos { diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs index ae7d82c2020..e77faea1e4c 100644 --- a/src/librustc/ich/hcx.rs +++ b/src/librustc/ich/hcx.rs @@ -350,7 +350,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for Span { let line_col_len = col | line | len; std_hash::Hash::hash(&line_col_len, hasher); - if span.ctxt == SyntaxContext::empty() { + if span.ctxt == SyntaxContext::root() { TAG_NO_EXPANSION.hash_stable(hcx, hasher); } else { TAG_EXPANSION.hash_stable(hcx, hasher); @@ -370,7 +370,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for Span { } let mut hasher = StableHasher::new(); - expn_id.expn_info().hash_stable(hcx, &mut hasher); + expn_id.expn_data().hash_stable(hcx, &mut hasher); let sub_hash: Fingerprint = hasher.finish(); let sub_hash = sub_hash.to_smaller_hash(); cache.borrow_mut().insert(expn_id, sub_hash); diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index 30d76f240d1..60b338010b0 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -153,8 +153,6 @@ impl<'a> HashStable<StableHashingContext<'a>> for hir::Ty { } } -impl_stable_hash_for_spanned!(hir::FieldPat); - impl_stable_hash_for_spanned!(hir::BinOpKind); impl_stable_hash_for!(struct hir::Stmt { @@ -187,8 +185,6 @@ impl<'a> HashStable<StableHashingContext<'a>> for hir::Expr { impl_stable_hash_for_spanned!(usize); -impl_stable_hash_for_spanned!(ast::Ident); - impl_stable_hash_for!(struct ast::Ident { name, span, @@ -304,7 +300,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for hir::Mod { } } -impl_stable_hash_for_spanned!(hir::VariantKind); +impl_stable_hash_for_spanned!(hir::Variant); impl<'a> HashStable<StableHashingContext<'a>> for hir::Item { diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index 5cc8324b316..7003f71c8ba 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -397,9 +397,10 @@ impl_stable_hash_for!(enum ::syntax_pos::hygiene::Transparency { Opaque, }); -impl_stable_hash_for!(struct ::syntax_pos::hygiene::ExpnInfo { - call_site, +impl_stable_hash_for!(struct ::syntax_pos::hygiene::ExpnData { kind, + parent -> _, + call_site, def_site, default_transparency, allow_internal_unstable, diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 2ffcd2c4ace..84687b8cab5 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -1329,7 +1329,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let generics = self.tcx.generics_of(did); // Account for the case where `did` corresponds to `Self`, which doesn't have // the expected type argument. - if !param.is_self() { + if !(generics.has_self && param.index == 0) { let type_param = generics.type_param(param, self.tcx); let hir = &self.tcx.hir(); hir.as_local_hir_id(type_param.def_id).map(|id| { @@ -1337,7 +1337,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // We do this to avoid suggesting code that ends up as `T: 'a'b`, // instead we suggest `T: 'a + 'b` in that case. let mut has_bounds = false; - if let Node::GenericParam(ref param) = hir.get(id) { + if let Node::GenericParam(param) = hir.get(id) { has_bounds = !param.bounds.is_empty(); } let sp = hir.span(id); diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs index 770d5155777..3267505708b 100644 --- a/src/librustc/infer/error_reporting/need_type_info.rs +++ b/src/librustc/infer/error_reporting/need_type_info.rs @@ -1,5 +1,5 @@ use crate::hir::def::Namespace; -use crate::hir::{self, Local, Pat, Body, HirId}; +use crate::hir::{self, Body, FunctionRetTy, Expr, ExprKind, HirId, Local, Pat}; use crate::hir::intravisit::{self, Visitor, NestedVisitorMap}; use crate::infer::InferCtxt; use crate::infer::type_variable::TypeVariableOriginKind; @@ -7,7 +7,7 @@ use crate::ty::{self, Ty, Infer, TyVar}; use crate::ty::print::Print; use syntax::source_map::DesugaringKind; use syntax_pos::Span; -use errors::DiagnosticBuilder; +use errors::{Applicability, DiagnosticBuilder}; struct FindLocalByTypeVisitor<'a, 'tcx> { infcx: &'a InferCtxt<'a, 'tcx>, @@ -16,9 +16,26 @@ struct FindLocalByTypeVisitor<'a, 'tcx> { found_local_pattern: Option<&'tcx Pat>, found_arg_pattern: Option<&'tcx Pat>, found_ty: Option<Ty<'tcx>>, + found_closure: Option<&'tcx ExprKind>, } impl<'a, 'tcx> FindLocalByTypeVisitor<'a, 'tcx> { + fn new( + infcx: &'a InferCtxt<'a, 'tcx>, + target_ty: Ty<'tcx>, + hir_map: &'a hir::map::Map<'tcx>, + ) -> Self { + Self { + infcx, + target_ty, + hir_map, + found_local_pattern: None, + found_arg_pattern: None, + found_ty: None, + found_closure: None, + } + } + fn node_matches_type(&mut self, hir_id: HirId) -> Option<Ty<'tcx>> { let ty_opt = self.infcx.in_progress_tables.and_then(|tables| { tables.borrow().node_type_opt(hir_id) @@ -72,6 +89,60 @@ impl<'a, 'tcx> Visitor<'tcx> for FindLocalByTypeVisitor<'a, 'tcx> { } intravisit::walk_body(self, body); } + + fn visit_expr(&mut self, expr: &'tcx Expr) { + if let (ExprKind::Closure(_, _fn_decl, _id, _sp, _), Some(_)) = ( + &expr.node, + self.node_matches_type(expr.hir_id), + ) { + self.found_closure = Some(&expr.node); + } + intravisit::walk_expr(self, expr); + } +} + +/// Suggest giving an appropriate return type to a closure expression. +fn closure_return_type_suggestion( + span: Span, + err: &mut DiagnosticBuilder<'_>, + output: &FunctionRetTy, + body: &Body, + name: &str, + ret: &str, +) { + let (arrow, post) = match output { + FunctionRetTy::DefaultReturn(_) => ("-> ", " "), + _ => ("", ""), + }; + let suggestion = match body.value.node { + ExprKind::Block(..) => { + vec![(output.span(), format!("{}{}{}", arrow, ret, post))] + } + _ => { + vec![ + (output.span(), format!("{}{}{}{{ ", arrow, ret, post)), + (body.value.span.shrink_to_hi(), " }".to_string()), + ] + } + }; + err.multipart_suggestion( + "give this closure an explicit return type without `_` placeholders", + suggestion, + Applicability::HasPlaceholders, + ); + err.span_label(span, InferCtxt::missing_type_msg(&name)); +} + +/// Given a closure signature, return a `String` containing a list of all its argument types. +fn closure_args(fn_sig: &ty::PolyFnSig<'_>) -> String { + fn_sig.inputs() + .skip_binder() + .iter() + .next() + .map(|args| args.tuple_fields() + .map(|arg| arg.to_string()) + .collect::<Vec<_>>().join(", ")) + .unwrap_or_default() } impl<'a, 'tcx> InferCtxt<'a, 'tcx> { @@ -106,16 +177,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let ty = self.resolve_vars_if_possible(&ty); let name = self.extract_type_name(&ty, None); - let mut err_span = span; - - let mut local_visitor = FindLocalByTypeVisitor { - infcx: &self, - target_ty: ty, - hir_map: &self.tcx.hir(), - found_local_pattern: None, - found_arg_pattern: None, - found_ty: None, - }; + let mut local_visitor = FindLocalByTypeVisitor::new(&self, ty, &self.tcx.hir()); let ty_to_string = |ty: Ty<'tcx>| -> String { let mut s = String::new(); let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS); @@ -136,6 +198,31 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let expr = self.tcx.hir().expect_expr(body_id.hir_id); local_visitor.visit_expr(expr); } + let err_span = if let Some(pattern) = local_visitor.found_arg_pattern { + pattern.span + } else { + span + }; + + let is_named_and_not_impl_trait = |ty: Ty<'_>| { + &ty.to_string() != "_" && + // FIXME: Remove this check after `impl_trait_in_bindings` is stabilized. #63527 + (!ty.is_impl_trait() || self.tcx.features().impl_trait_in_bindings) + }; + + let ty_msg = match local_visitor.found_ty { + Some(ty::TyS { sty: ty::Closure(def_id, substs), .. }) => { + let fn_sig = substs.closure_sig(*def_id, self.tcx); + let args = closure_args(&fn_sig); + let ret = fn_sig.output().skip_binder().to_string(); + format!(" for the closure `fn({}) -> {}`", args, ret) + } + Some(ty) if is_named_and_not_impl_trait(ty) => { + let ty = ty_to_string(ty); + format!(" for `{}`", ty) + } + _ => String::new(), + }; // When `name` corresponds to a type argument, show the path of the full type we're // trying to infer. In the following example, `ty_msg` contains @@ -150,27 +237,58 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // | consider giving `b` the explicit type `std::result::Result<i32, E>`, where // | the type parameter `E` is specified // ``` - let (ty_msg, suffix) = match &local_visitor.found_ty { - Some(ty) if &ty.to_string() != "_" && name == "_" => { + let mut err = struct_span_err!( + self.tcx.sess, + err_span, + E0282, + "type annotations needed{}", + ty_msg, + ); + + let suffix = match local_visitor.found_ty { + Some(ty::TyS { sty: ty::Closure(def_id, substs), .. }) => { + let fn_sig = substs.closure_sig(*def_id, self.tcx); + let ret = fn_sig.output().skip_binder().to_string(); + + if let Some(ExprKind::Closure(_, decl, body_id, ..)) = local_visitor.found_closure { + if let Some(body) = self.tcx.hir().krate().bodies.get(body_id) { + closure_return_type_suggestion( + span, + &mut err, + &decl.output, + &body, + &name, + &ret, + ); + // We don't want to give the other suggestions when the problem is the + // closure return type. + return err; + } + } + + // This shouldn't be reachable, but just in case we leave a reasonable fallback. + let args = closure_args(&fn_sig); + // This suggestion is incomplete, as the user will get further type inference + // errors due to the `_` placeholders and the introduction of `Box`, but it does + // nudge them in the right direction. + format!("a boxed closure type like `Box<dyn Fn({}) -> {}>`", args, ret) + } + Some(ty) if is_named_and_not_impl_trait(ty) && name == "_" => { let ty = ty_to_string(ty); - (format!(" for `{}`", ty), - format!("the explicit type `{}`, with the type parameters specified", ty)) + format!("the explicit type `{}`, with the type parameters specified", ty) } - Some(ty) if &ty.to_string() != "_" && ty.to_string() != name => { + Some(ty) if is_named_and_not_impl_trait(ty) && ty.to_string() != name => { let ty = ty_to_string(ty); - (format!(" for `{}`", ty), - format!( - "the explicit type `{}`, where the type parameter `{}` is specified", + format!( + "the explicit type `{}`, where the type parameter `{}` is specified", ty, name, - )) + ) } - _ => (String::new(), "a type".to_owned()), + _ => "a type".to_string(), }; - let mut labels = vec![(span, InferCtxt::missing_type_msg(&name))]; if let Some(pattern) = local_visitor.found_arg_pattern { - err_span = pattern.span; // We don't want to show the default label for closures. // // So, before clearing, the output would look something like this: @@ -187,39 +305,31 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // ^ consider giving this closure parameter the type `[_; 0]` // with the type parameter `_` specified // ``` - labels.clear(); - labels.push(( + err.span_label( pattern.span, format!("consider giving this closure parameter {}", suffix), - )); + ); } else if let Some(pattern) = local_visitor.found_local_pattern { - if let Some(simple_ident) = pattern.simple_ident() { + let msg = if let Some(simple_ident) = pattern.simple_ident() { match pattern.span.desugaring_kind() { - None => labels.push(( - pattern.span, - format!("consider giving `{}` {}", simple_ident, suffix), - )), - Some(DesugaringKind::ForLoop) => labels.push(( - pattern.span, - "the element type for this iterator is not specified".to_owned(), - )), - _ => {} + None => { + format!("consider giving `{}` {}", simple_ident, suffix) + } + Some(DesugaringKind::ForLoop) => { + "the element type for this iterator is not specified".to_string() + } + _ => format!("this needs {}", suffix), } } else { - labels.push((pattern.span, format!("consider giving this pattern {}", suffix))); - } - }; - - let mut err = struct_span_err!( - self.tcx.sess, - err_span, - E0282, - "type annotations needed{}", - ty_msg, - ); - - for (target_span, label_message) in labels { - err.span_label(target_span, label_message); + format!("consider giving this pattern {}", suffix) + }; + err.span_label(pattern.span, msg); + } + if !err.span.span_labels().iter().any(|span_label| { + span_label.label.is_some() && span_label.span == span + }) && local_visitor.found_arg_pattern.is_none() + { // Avoid multiple labels pointing at `span`. + err.span_label(span, InferCtxt::missing_type_msg(&name)); } err diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs index 5c62f76e3bb..c9fd3392a96 100644 --- a/src/librustc/infer/opaque_types/mod.rs +++ b/src/librustc/infer/opaque_types/mod.rs @@ -127,8 +127,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ) -> InferOk<'tcx, (T, OpaqueTypeMap<'tcx>)> { debug!( "instantiate_opaque_types(value={:?}, parent_def_id={:?}, body_id={:?}, \ - param_env={:?})", - value, parent_def_id, body_id, param_env, + param_env={:?}, value_span={:?})", + value, parent_def_id, body_id, param_env, value_span, ); let mut instantiator = Instantiator { infcx: self, @@ -1108,9 +1108,11 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { // Use the same type variable if the exact same opaque type appears more // than once in the return type (e.g., if it's passed to a type alias). if let Some(opaque_defn) = self.opaque_types.get(&def_id) { + debug!("instantiate_opaque_types: returning concrete ty {:?}", opaque_defn.concrete_ty); return opaque_defn.concrete_ty; } let span = tcx.def_span(def_id); + debug!("fold_opaque_ty {:?} {:?}", self.value_span, span); let ty_var = infcx .next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span }); diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index de812410e8b..6801fa8d8db 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -1060,7 +1060,7 @@ for LateContextAndPass<'a, 'tcx, T> { v: &'tcx hir::Variant, g: &'tcx hir::Generics, item_id: hir::HirId) { - self.with_lint_attrs(v.node.id, &v.node.attrs, |cx| { + self.with_lint_attrs(v.id, &v.attrs, |cx| { lint_callback!(cx, check_variant, v, g); hir_visit::walk_variant(cx, v, g, item_id); lint_callback!(cx, check_variant_post, v, g); @@ -1236,7 +1236,7 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> } fn visit_variant(&mut self, v: &'a ast::Variant, g: &'a ast::Generics, item_id: ast::NodeId) { - self.with_lint_attrs(item_id, &v.node.attrs, |cx| { + self.with_lint_attrs(item_id, &v.attrs, |cx| { run_early_pass!(cx, check_variant, v, g); ast_visit::walk_variant(cx, v, g, item_id); run_early_pass!(cx, check_variant_post, v, g); @@ -1345,7 +1345,7 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> // part of `walk_mac`, and (b) we should be calling // `visit_path`, *but* that would require a `NodeId`, and I // want to get #53686 fixed quickly. -nmatsakis - ast_visit::walk_path(self, &mac.node.path); + ast_visit::walk_path(self, &mac.path); run_early_pass!(self, check_mac, mac); } @@ -1355,7 +1355,7 @@ struct LateLintPassObjects<'a> { lints: &'a mut [LateLintPassObject], } -#[cfg_attr(not(bootstrap), allow(rustc::lint_pass_impl_without_macro))] +#[allow(rustc::lint_pass_impl_without_macro)] impl LintPass for LateLintPassObjects<'_> { fn name(&self) -> &'static str { panic!() @@ -1525,7 +1525,7 @@ struct EarlyLintPassObjects<'a> { lints: &'a mut [EarlyLintPassObject], } -#[cfg_attr(not(bootstrap), allow(rustc::lint_pass_impl_without_macro))] +#[allow(rustc::lint_pass_impl_without_macro)] impl LintPass for EarlyLintPassObjects<'_> { fn name(&self) -> &'static str { panic!() diff --git a/src/librustc/lint/internal.rs b/src/librustc/lint/internal.rs index 0b514f5927d..be73b305e2c 100644 --- a/src/librustc/lint/internal.rs +++ b/src/librustc/lint/internal.rs @@ -9,7 +9,6 @@ use errors::Applicability; use rustc_data_structures::fx::FxHashMap; use syntax::ast::{Ident, Item, ItemKind}; use syntax::symbol::{sym, Symbol}; -use syntax_pos::ExpnInfo; declare_tool_lint! { pub rustc::DEFAULT_HASH_TYPES, @@ -23,7 +22,7 @@ pub struct DefaultHashTypes { impl DefaultHashTypes { // we are allowed to use `HashMap` and `HashSet` as identifiers for implementing the lint itself - #[cfg_attr(not(bootstrap), allow(rustc::default_hash_types))] + #[allow(rustc::default_hash_types)] pub fn new() -> Self { let mut map = FxHashMap::default(); map.insert(sym::HashMap, sym::FxHashMap); @@ -108,7 +107,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TyTyKind { .help("try using `Ty` instead") .emit(); } else { - if ty.span.ctxt().outer_expn_info().is_some() { + if ty.span.from_expansion() { return; } if let Some(t) = is_ty_or_ty_ctxt(cx, ty) { @@ -228,30 +227,20 @@ impl EarlyLintPass for LintPassImpl { if let ItemKind::Impl(_, _, _, _, Some(lint_pass), _, _) = &item.node { if let Some(last) = lint_pass.path.segments.last() { if last.ident.name == sym::LintPass { - match &lint_pass.path.span.ctxt().outer_expn_info() { - Some(info) if is_lint_pass_expansion(info) => {} - _ => { - cx.struct_span_lint( - LINT_PASS_IMPL_WITHOUT_MACRO, - lint_pass.path.span, - "implementing `LintPass` by hand", - ) - .help("try using `declare_lint_pass!` or `impl_lint_pass!` instead") - .emit(); - } + let expn_data = lint_pass.path.span.ctxt().outer_expn_data(); + let call_site = expn_data.call_site; + if expn_data.kind.descr() != sym::impl_lint_pass && + call_site.ctxt().outer_expn_data().kind.descr() != sym::declare_lint_pass { + cx.struct_span_lint( + LINT_PASS_IMPL_WITHOUT_MACRO, + lint_pass.path.span, + "implementing `LintPass` by hand", + ) + .help("try using `declare_lint_pass!` or `impl_lint_pass!` instead") + .emit(); } } } } } } - -fn is_lint_pass_expansion(expn_info: &ExpnInfo) -> bool { - if expn_info.kind.descr() == sym::impl_lint_pass { - true - } else if let Some(info) = expn_info.call_site.ctxt().outer_expn_info() { - info.kind.descr() == sym::declare_lint_pass - } else { - false - } -} diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 8ddf4603490..2b58627cdea 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -846,7 +846,7 @@ impl intravisit::Visitor<'tcx> for LintLevelMapBuilder<'tcx> { v: &'tcx hir::Variant, g: &'tcx hir::Generics, item_id: hir::HirId) { - self.with_lint_attrs(v.node.id, &v.node.attrs, |builder| { + self.with_lint_attrs(v.id, &v.attrs, |builder| { intravisit::walk_variant(builder, v, g, item_id); }) } @@ -885,21 +885,16 @@ pub fn provide(providers: &mut Providers<'_>) { /// This is used to test whether a lint should not even begin to figure out whether it should /// be reported on the current node. pub fn in_external_macro(sess: &Session, span: Span) -> bool { - let info = match span.ctxt().outer_expn_info() { - Some(info) => info, - // no ExpnInfo means this span doesn't come from a macro - None => return false, - }; - - match info.kind { + let expn_data = span.ctxt().outer_expn_data(); + match expn_data.kind { ExpnKind::Root | ExpnKind::Desugaring(DesugaringKind::ForLoop) => false, ExpnKind::Desugaring(_) => true, // well, it's "external" ExpnKind::Macro(MacroKind::Bang, _) => { - if info.def_site.is_dummy() { + if expn_data.def_site.is_dummy() { // dummy span for the def_site means it's an external macro return true; } - match sess.source_map().span_to_snippet(info.def_site) { + match sess.source_map().span_to_snippet(expn_data.def_site) { Ok(code) => !code.starts_with("macro_rules"), // no snippet = external macro or compiler-builtin expansion Err(_) => true, @@ -911,10 +906,8 @@ pub fn in_external_macro(sess: &Session, span: Span) -> bool { /// Returns whether `span` originates in a derive macro's expansion pub fn in_derive_expansion(span: Span) -> bool { - if let Some(info) = span.ctxt().outer_expn_info() { - if let ExpnKind::Macro(MacroKind::Derive, _) = info.kind { - return true; - } + if let ExpnKind::Macro(MacroKind::Derive, _) = span.ctxt().outer_expn_data().kind { + return true; } false } diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index d37b2367ae7..de84fcd7160 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -178,8 +178,7 @@ pub trait MetadataLoader { -> Result<MetadataRef, String>; } -/// A store of Rust crates, through with their metadata -/// can be accessed. +/// A store of Rust crates, through which their metadata can be accessed. /// /// Note that this trait should probably not be expanding today. All new /// functionality should be driven through queries instead! diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 55fa261f1ed..8ce8bb52566 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -17,8 +17,7 @@ use crate::util::nodemap::FxHashSet; use rustc_data_structures::fx::FxHashMap; -use syntax::{ast, source_map}; -use syntax::attr; +use syntax::{ast, attr}; use syntax::symbol::sym; use syntax_pos; @@ -119,17 +118,16 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { } } - fn handle_field_pattern_match(&mut self, lhs: &hir::Pat, res: Res, - pats: &[source_map::Spanned<hir::FieldPat>]) { + fn handle_field_pattern_match(&mut self, lhs: &hir::Pat, res: Res, pats: &[hir::FieldPat]) { let variant = match self.tables.node_type(lhs.hir_id).sty { ty::Adt(adt, _) => adt.variant_of_res(res), _ => span_bug!(lhs.span, "non-ADT in struct pattern") }; for pat in pats { - if let PatKind::Wild = pat.node.pat.node { + if let PatKind::Wild = pat.pat.node { continue; } - let index = self.tcx.field_index(pat.node.hir_id, self.tables); + let index = self.tcx.field_index(pat.hir_id, self.tables); self.insert_def_id(variant.fields[index].did); } } @@ -366,12 +364,12 @@ impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> { match item.node { hir::ItemKind::Enum(ref enum_def, _) => { if allow_dead_code { - self.worklist.extend(enum_def.variants.iter().map(|variant| variant.node.id)); + self.worklist.extend(enum_def.variants.iter().map(|variant| variant.id)); } for variant in &enum_def.variants { - if let Some(ctor_hir_id) = variant.node.data.ctor_hir_id() { - self.struct_constructors.insert(ctor_hir_id, variant.node.id); + if let Some(ctor_hir_id) = variant.data.ctor_hir_id() { + self.struct_constructors.insert(ctor_hir_id, variant.id); } } } @@ -497,7 +495,7 @@ impl DeadVisitor<'tcx> { && !has_allow_dead_code_or_lang_attr(self.tcx, field.hir_id, &field.attrs) } - fn should_warn_about_variant(&mut self, variant: &hir::VariantKind) -> bool { + fn should_warn_about_variant(&mut self, variant: &hir::Variant) -> bool { !self.symbol_is_live(variant.id) && !has_allow_dead_code_or_lang_attr(self.tcx, variant.id, @@ -596,8 +594,8 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> { variant: &'tcx hir::Variant, g: &'tcx hir::Generics, id: hir::HirId) { - if self.should_warn_about_variant(&variant.node) { - self.warn_dead_code(variant.node.id, variant.span, variant.node.ident.name, + if self.should_warn_about_variant(&variant) { + self.warn_dead_code(variant.id, variant.span, variant.ident.name, "variant", "constructed"); } else { intravisit::walk_variant(self, variant, g, id); diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index daf0d8103a2..9c9e8c0bca3 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -418,8 +418,8 @@ fn add_from_pat<'tcx>(ir: &mut IrMaps<'tcx>, pat: &P<hir::Pat>) { } Struct(_, ref fields, _) => { for field in fields { - if field.node.is_shorthand { - shorthand_field_ids.insert(field.node.pat.hir_id); + if field.is_shorthand { + shorthand_field_ids.insert(field.pat.hir_id); } } } diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 77d6f393244..73ca981bbe8 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -1282,11 +1282,17 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { }; for fp in field_pats { - let field_ty = self.pat_ty_adjusted(&fp.node.pat)?; // see (*2) - let f_index = self.tcx.field_index(fp.node.hir_id, self.tables); + let field_ty = self.pat_ty_adjusted(&fp.pat)?; // see (*2) + let f_index = self.tcx.field_index(fp.hir_id, self.tables); let cmt_field = Rc::new(self.cat_field(pat, cmt.clone(), f_index, - fp.node.ident, field_ty)); - self.cat_pattern_(cmt_field, &fp.node.pat, op)?; + fp.ident, field_ty)); + self.cat_pattern_(cmt_field, &fp.pat, op)?; + } + } + + PatKind::Or(ref pats) => { + for pat in pats { + self.cat_pattern_(cmt.clone(), &pat, op)?; } } diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 76d8a6738f0..c2bcd462163 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -33,6 +33,9 @@ fn item_might_be_inlined(tcx: TyCtxt<'tcx>, item: &hir::Item, attrs: CodegenFnAt } match item.node { + hir::ItemKind::Fn(_, header, ..) if header.is_const() => { + return true; + } hir::ItemKind::Impl(..) | hir::ItemKind::Fn(..) => { let generics = tcx.generics_of(tcx.hir().local_def_id(item.hir_id)); @@ -52,6 +55,11 @@ fn method_might_be_inlined( if codegen_fn_attrs.requests_inline() || generics.requires_monomorphization(tcx) { return true } + if let hir::ImplItemKind::Method(method_sig, _) = &impl_item.node { + if method_sig.header.is_const() { + return true + } + } if let Some(impl_hir_id) = tcx.hir().as_local_hir_id(impl_src) { match tcx.hir().find(impl_hir_id) { Some(Node::Item(item)) => diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 88c19715811..3d100d2fbf8 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -1207,7 +1207,7 @@ fn resolve_local<'tcx>( PatKind::Binding(hir::BindingAnnotation::RefMut, ..) => true, PatKind::Struct(_, ref field_pats, _) => { - field_pats.iter().any(|fp| is_binding_pat(&fp.node.pat)) + field_pats.iter().any(|fp| is_binding_pat(&fp.pat)) } PatKind::Slice(ref pats1, ref pats2, ref pats3) => { diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index f8f01f79e1d..f5b0af61693 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -5,6 +5,8 @@ //! used between functions, and they operate in a purely top-down //! way. Therefore, we break lifetime name resolution into a separate pass. +// ignore-tidy-filelength + use crate::hir::def::{Res, DefKind}; use crate::hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; use crate::hir::map::Map; @@ -556,6 +558,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { fn visit_ty(&mut self, ty: &'tcx hir::Ty) { debug!("visit_ty: id={:?} ty={:?}", ty.hir_id, ty); + debug!("visit_ty: ty.node={:?}", ty.node); match ty.node { hir::TyKind::BareFn(ref c) => { let next_early_index = self.next_early_index(); @@ -585,11 +588,20 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { self.is_in_fn_syntax = was_in_fn_syntax; } hir::TyKind::TraitObject(ref bounds, ref lifetime) => { + debug!("visit_ty: TraitObject(bounds={:?}, lifetime={:?})", bounds, lifetime); for bound in bounds { self.visit_poly_trait_ref(bound, hir::TraitBoundModifier::None); } match lifetime.name { LifetimeName::Implicit => { + // For types like `dyn Foo`, we should + // generate a special form of elided. + span_bug!( + ty.span, + "object-lifetime-default expected, not implict", + ); + } + LifetimeName::ImplicitObjectLifetimeDefault => { // If the user does not write *anything*, we // use the object lifetime defaulting // rules. So e.g., `Box<dyn Debug>` becomes @@ -897,6 +909,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) { + debug!("visit_lifetime(lifetime_ref={:?})", lifetime_ref); if lifetime_ref.is_elided() { self.resolve_elided_lifetimes(vec![lifetime_ref]); return; @@ -1911,6 +1924,13 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } fn visit_segment_args(&mut self, res: Res, depth: usize, generic_args: &'tcx hir::GenericArgs) { + debug!( + "visit_segment_args(res={:?}, depth={:?}, generic_args={:?})", + res, + depth, + generic_args, + ); + if generic_args.parenthesized { let was_in_fn_syntax = self.is_in_fn_syntax; self.is_in_fn_syntax = true; @@ -1964,6 +1984,23 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { _ => None, }; + debug!("visit_segment_args: type_def_id={:?}", type_def_id); + + // Compute a vector of defaults, one for each type parameter, + // per the rules given in RFCs 599 and 1156. Example: + // + // ```rust + // struct Foo<'a, T: 'a, U> { } + // ``` + // + // If you have `Foo<'x, dyn Bar, dyn Baz>`, we want to default + // `dyn Bar` to `dyn Bar + 'x` (because of the `T: 'a` bound) + // and `dyn Baz` to `dyn Baz + 'static` (because there is no + // such bound). + // + // Therefore, we would compute `object_lifetime_defaults` to a + // vector like `['x, 'static]`. Note that the vector only + // includes type parameters. let object_lifetime_defaults = type_def_id.map_or(vec![], |def_id| { let in_body = { let mut scope = self.scope; @@ -2003,6 +2040,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { .collect() }) }; + debug!("visit_segment_args: unsubst={:?}", unsubst); unsubst .iter() .map(|set| match *set { @@ -2023,6 +2061,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { .collect() }); + debug!("visit_segment_args: object_lifetime_defaults={:?}", object_lifetime_defaults); + let mut i = 0; for arg in &generic_args.args { match arg { @@ -2045,8 +2085,49 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } } + // Hack: when resolving the type `XX` in binding like `dyn + // Foo<'b, Item = XX>`, the current object-lifetime default + // would be to examine the trait `Foo` to check whether it has + // a lifetime bound declared on `Item`. e.g., if `Foo` is + // declared like so, then the default object lifetime bound in + // `XX` should be `'b`: + // + // ```rust + // trait Foo<'a> { + // type Item: 'a; + // } + // ``` + // + // but if we just have `type Item;`, then it would be + // `'static`. However, we don't get all of this logic correct. + // + // Instead, we do something hacky: if there are no lifetime parameters + // to the trait, then we simply use a default object lifetime + // bound of `'static`, because there is no other possibility. On the other hand, + // if there ARE lifetime parameters, then we require the user to give an + // explicit bound for now. + // + // This is intended to leave room for us to implement the + // correct behavior in the future. + let has_lifetime_parameter = generic_args + .args + .iter() + .any(|arg| match arg { + GenericArg::Lifetime(_) => true, + _ => false, + }); + + // Resolve lifetimes found in the type `XX` from `Item = XX` bindings. for b in &generic_args.bindings { - self.visit_assoc_type_binding(b); + let scope = Scope::ObjectLifetimeDefault { + lifetime: if has_lifetime_parameter { + None + } else { + Some(Region::Static) + }, + s: self.scope, + }; + self.with(scope, |_, this| this.visit_assoc_type_binding(b)); } } @@ -2347,6 +2428,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } fn resolve_elided_lifetimes(&mut self, lifetime_refs: Vec<&'tcx hir::Lifetime>) { + debug!("resolve_elided_lifetimes(lifetime_refs={:?})", lifetime_refs); + if lifetime_refs.is_empty() { return; } @@ -2539,6 +2622,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } fn resolve_object_lifetime_default(&mut self, lifetime_ref: &'tcx hir::Lifetime) { + debug!("resolve_object_lifetime_default(lifetime_ref={:?})", lifetime_ref); let mut late_depth = 0; let mut scope = self.scope; let lifetime = loop { @@ -2638,6 +2722,13 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { hir::LifetimeName::Param(_) | hir::LifetimeName::Implicit => { self.resolve_lifetime_ref(lt); } + hir::LifetimeName::ImplicitObjectLifetimeDefault => { + self.tcx.sess.delay_span_bug( + lt.span, + "lowering generated `ImplicitObjectLifetimeDefault` \ + outside of an object type", + ) + } hir::LifetimeName::Error => { // No need to do anything, error already reported. } diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 5ab762ab225..d02259bf301 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -290,10 +290,10 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { } fn visit_variant(&mut self, var: &'tcx Variant, g: &'tcx Generics, item_id: HirId) { - self.annotate(var.node.id, &var.node.attrs, var.span, AnnotationKind::Required, + self.annotate(var.id, &var.attrs, var.span, AnnotationKind::Required, |v| { - if let Some(ctor_hir_id) = var.node.data.ctor_hir_id() { - v.annotate(ctor_hir_id, &var.node.attrs, var.span, AnnotationKind::Required, + if let Some(ctor_hir_id) = var.data.ctor_hir_id() { + v.annotate(ctor_hir_id, &var.attrs, var.span, AnnotationKind::Required, |_| {}); } @@ -372,7 +372,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'a, 'tcx> { } fn visit_variant(&mut self, var: &'tcx Variant, g: &'tcx Generics, item_id: HirId) { - self.check_missing_stability(var.node.id, var.span, "variant"); + self.check_missing_stability(var.id, var.span, "variant"); intravisit::walk_variant(self, var, g, item_id); } diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index ce04cca96e0..84b4cd91456 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -306,7 +306,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> { /// /// zsts can't be read out of two reasons: /// * byteorder cannot work with zero element buffers - /// * in oder to obtain a `Pointer` we need to check for ZSTness anyway due to integer pointers + /// * in order to obtain a `Pointer` we need to check for ZSTness anyway due to integer pointers /// being valid for ZSTs /// /// It is the caller's responsibility to check bounds and alignment beforehand. diff --git a/src/librustc/mir/interpret/pointer.rs b/src/librustc/mir/interpret/pointer.rs index 0a998513379..b55e6bc54bc 100644 --- a/src/librustc/mir/interpret/pointer.rs +++ b/src/librustc/mir/interpret/pointer.rs @@ -189,8 +189,11 @@ impl<'tcx, Tag> Pointer<Tag> { Pointer { alloc_id: self.alloc_id, offset: self.offset, tag: () } } + /// Test if the pointer is "inbounds" of an allocation of the given size. + /// A pointer is "inbounds" even if its offset is equal to the size; this is + /// a "one-past-the-end" pointer. #[inline(always)] - pub fn check_in_alloc( + pub fn check_inbounds_alloc( self, allocation_size: Size, msg: CheckInAllocMsg, diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs index 5381d469724..3da5a65c379 100644 --- a/src/librustc/mir/interpret/value.rs +++ b/src/librustc/mir/interpret/value.rs @@ -530,7 +530,7 @@ impl<'tcx, Tag> ScalarMaybeUndef<Tag> { pub fn not_undef(self) -> InterpResult<'static, Scalar<Tag>> { match self { ScalarMaybeUndef::Scalar(scalar) => Ok(scalar), - ScalarMaybeUndef::Undef => throw_unsup!(ReadUndefBytes(Size::from_bytes(0))), + ScalarMaybeUndef::Undef => throw_unsup!(ReadUndefBytes(Size::ZERO)), } } diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 1e2ec08301c..11701a66377 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2197,7 +2197,6 @@ impl<'tcx> Operand<'tcx> { let ty = tcx.type_of(def_id).subst(tcx, substs); Operand::Constant(box Constant { span, - ty, user_ty: None, literal: ty::Const::zero_sized(tcx, ty), }) @@ -2476,7 +2475,6 @@ impl<'tcx> Debug for Rvalue<'tcx> { #[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)] pub struct Constant<'tcx> { pub span: Span, - pub ty: Ty<'tcx>, /// Optional user-given type: for something like /// `collect::<Vec<_>>`, this would be present and would @@ -3385,12 +3383,11 @@ impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> { fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self { Constant { span: self.span.clone(), - ty: self.ty.fold_with(folder), user_ty: self.user_ty.fold_with(folder), literal: self.literal.fold_with(folder), } } fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool { - self.ty.visit_with(visitor) || self.literal.visit_with(visitor) + self.literal.visit_with(visitor) } } diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index f8889380b2a..e9f7636ba85 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -252,7 +252,7 @@ impl<'tcx> Operand<'tcx> { match self { &Operand::Copy(ref l) | &Operand::Move(ref l) => l.ty(local_decls, tcx).ty, - &Operand::Constant(ref c) => c.ty, + &Operand::Constant(ref c) => c.literal.ty, } } } diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index ee4ecb6762c..2d16e7bcc83 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -782,13 +782,11 @@ macro_rules! make_mir_visitor { location: Location) { let Constant { span, - ty, user_ty, literal, } = constant; self.visit_span(span); - self.visit_ty(ty, TyContext::Location(location)); drop(user_ty); // no visit method for this self.visit_const(literal, location); } diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 3536b2aa8ff..8e3b910e0da 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -395,7 +395,7 @@ top_level_options!( output_types: OutputTypes [TRACKED], search_paths: Vec<SearchPath> [UNTRACKED], libs: Vec<(String, Option<String>, Option<cstore::NativeLibraryKind>)> [TRACKED], - maybe_sysroot: Option<PathBuf> [TRACKED], + maybe_sysroot: Option<PathBuf> [UNTRACKED], target_triple: TargetTriple [TRACKED], diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 83bd5c56040..ba92e851141 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -36,7 +36,7 @@ use errors::{Applicability, DiagnosticBuilder}; use std::fmt; use syntax::ast; use syntax::symbol::sym; -use syntax_pos::{DUMMY_SP, Span, ExpnInfo, ExpnKind}; +use syntax_pos::{DUMMY_SP, Span, ExpnKind}; impl<'a, 'tcx> InferCtxt<'a, 'tcx> { pub fn report_fulfillment_errors(&self, @@ -61,9 +61,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // We want to ignore desugarings here: spans are equivalent even // if one is the result of a desugaring and the other is not. let mut span = error.obligation.cause.span; - if let Some(ExpnInfo { kind: ExpnKind::Desugaring(_), def_site, .. }) - = span.ctxt().outer_expn_info() { - span = def_site; + let expn_data = span.ctxt().outer_expn_data(); + if let ExpnKind::Desugaring(_) = expn_data.kind { + span = expn_data.call_site; } error_map.entry(span).or_default().push( diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index 99b5ef3894b..c1de4939c1d 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -248,10 +248,10 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> { /// This is always inlined, despite its size, because it has a single /// callsite and it is called *very* frequently. #[inline(always)] - fn process_obligation(&mut self, - pending_obligation: &mut Self::Obligation) - -> ProcessResult<Self::Obligation, Self::Error> - { + fn process_obligation( + &mut self, + pending_obligation: &mut Self::Obligation, + ) -> ProcessResult<Self::Obligation, Self::Error> { // if we were stalled on some unresolved variables, first check // whether any of them have been resolved; if not, don't bother // doing more work yet @@ -277,7 +277,7 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> { self.selcx.infcx().resolve_vars_if_possible(&obligation.predicate); } - debug!("process_obligation: obligation = {:?}", obligation); + debug!("process_obligation: obligation = {:?} cause = {:?}", obligation, obligation.cause); match obligation.predicate { ty::Predicate::Trait(ref data) => { @@ -425,10 +425,13 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> { } ty::Predicate::WellFormed(ty) => { - match ty::wf::obligations(self.selcx.infcx(), - obligation.param_env, - obligation.cause.body_id, - ty, obligation.cause.span) { + match ty::wf::obligations( + self.selcx.infcx(), + obligation.param_env, + obligation.cause.body_id, + ty, + obligation.cause.span, + ) { None => { pending_obligation.stalled_on = vec![ty]; ProcessResult::Unchanged diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index 37eff852abd..7ea7bf0257c 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -91,6 +91,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn astconv_object_safety_violations(self, trait_def_id: DefId) -> Vec<ObjectSafetyViolation> { + debug_assert!(self.generics_of(trait_def_id).has_self); let violations = traits::supertrait_def_ids(self, trait_def_id) .filter(|&def_id| self.predicates_reference_self(def_id, true)) .map(|_| ObjectSafetyViolation::SupertraitSelf) @@ -106,6 +107,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn object_safety_violations(self, trait_def_id: DefId) -> Vec<ObjectSafetyViolation> { + debug_assert!(self.generics_of(trait_def_id).has_self); debug!("object_safety_violations: {:?}", trait_def_id); traits::supertrait_def_ids(self, trait_def_id) @@ -113,9 +115,25 @@ impl<'tcx> TyCtxt<'tcx> { .collect() } - fn object_safety_violations_for_trait(self, trait_def_id: DefId) - -> Vec<ObjectSafetyViolation> - { + /// We say a method is *vtable safe* if it can be invoked on a trait + /// object. Note that object-safe traits can have some + /// non-vtable-safe methods, so long as they require `Self:Sized` or + /// otherwise ensure that they cannot be used when `Self=Trait`. + pub fn is_vtable_safe_method(self, trait_def_id: DefId, method: &ty::AssocItem) -> bool { + debug_assert!(self.generics_of(trait_def_id).has_self); + debug!("is_vtable_safe_method({:?}, {:?})", trait_def_id, method); + // Any method that has a `Self : Sized` requisite can't be called. + if self.generics_require_sized_self(method.def_id) { + return false; + } + + match self.virtual_call_violation_for_method(trait_def_id, method) { + None | Some(MethodViolationCode::WhereClauseReferencesSelf(_)) => true, + Some(_) => false, + } + } + + fn object_safety_violations_for_trait(self, trait_def_id: DefId) -> Vec<ObjectSafetyViolation> { // Check methods for violations. let mut violations: Vec<_> = self.associated_items(trait_def_id) .filter(|item| item.kind == ty::AssocKind::Method) @@ -163,14 +181,16 @@ impl<'tcx> TyCtxt<'tcx> { fn predicates_reference_self( self, trait_def_id: DefId, - supertraits_only: bool) -> bool - { + supertraits_only: bool, + ) -> bool { let trait_ref = ty::Binder::dummy(ty::TraitRef::identity(self, trait_def_id)); let predicates = if supertraits_only { self.super_predicates_of(trait_def_id) } else { self.predicates_of(trait_def_id) }; + let self_ty = self.types.self_param; + let has_self_ty = |t: Ty<'tcx>| t.walk().any(|t| t == self_ty); predicates .predicates .iter() @@ -179,7 +199,7 @@ impl<'tcx> TyCtxt<'tcx> { match predicate { ty::Predicate::Trait(ref data) => { // In the case of a trait predicate, we can skip the "self" type. - data.skip_binder().input_types().skip(1).any(|t| t.has_self_ty()) + data.skip_binder().input_types().skip(1).any(has_self_ty) } ty::Predicate::Projection(ref data) => { // And similarly for projections. This should be redundant with @@ -199,7 +219,7 @@ impl<'tcx> TyCtxt<'tcx> { .trait_ref(self) .input_types() .skip(1) - .any(|t| t.has_self_ty()) + .any(has_self_ty) } ty::Predicate::WellFormed(..) | ty::Predicate::ObjectSafe(..) | @@ -229,11 +249,11 @@ impl<'tcx> TyCtxt<'tcx> { let predicates = predicates.instantiate_identity(self).predicates; elaborate_predicates(self, predicates) .any(|predicate| match predicate { - ty::Predicate::Trait(ref trait_pred) if trait_pred.def_id() == sized_def_id => { - trait_pred.skip_binder().self_ty().is_self() + ty::Predicate::Trait(ref trait_pred) => { + trait_pred.def_id() == sized_def_id + && trait_pred.skip_binder().self_ty().is_param(0) } ty::Predicate::Projection(..) | - ty::Predicate::Trait(..) | ty::Predicate::Subtype(..) | ty::Predicate::RegionOutlives(..) | ty::Predicate::WellFormed(..) | @@ -248,11 +268,11 @@ impl<'tcx> TyCtxt<'tcx> { } /// Returns `Some(_)` if this method makes the containing trait not object safe. - fn object_safety_violation_for_method(self, - trait_def_id: DefId, - method: &ty::AssocItem) - -> Option<MethodViolationCode> - { + fn object_safety_violation_for_method( + self, + trait_def_id: DefId, + method: &ty::AssocItem, + ) -> Option<MethodViolationCode> { debug!("object_safety_violation_for_method({:?}, {:?})", trait_def_id, method); // Any method that has a `Self : Sized` requisite is otherwise // exempt from the regulations. @@ -263,36 +283,15 @@ impl<'tcx> TyCtxt<'tcx> { self.virtual_call_violation_for_method(trait_def_id, method) } - /// We say a method is *vtable safe* if it can be invoked on a trait - /// object. Note that object-safe traits can have some - /// non-vtable-safe methods, so long as they require `Self:Sized` or - /// otherwise ensure that they cannot be used when `Self=Trait`. - pub fn is_vtable_safe_method(self, - trait_def_id: DefId, - method: &ty::AssocItem) - -> bool - { - debug!("is_vtable_safe_method({:?}, {:?})", trait_def_id, method); - // Any method that has a `Self : Sized` requisite can't be called. - if self.generics_require_sized_self(method.def_id) { - return false; - } - - match self.virtual_call_violation_for_method(trait_def_id, method) { - None | Some(MethodViolationCode::WhereClauseReferencesSelf(_)) => true, - Some(_) => false, - } - } - /// Returns `Some(_)` if this method cannot be called on a trait /// object; this does not necessarily imply that the enclosing trait /// is not object safe, because the method might have a where clause /// `Self:Sized`. - fn virtual_call_violation_for_method(self, - trait_def_id: DefId, - method: &ty::AssocItem) - -> Option<MethodViolationCode> - { + fn virtual_call_violation_for_method( + self, + trait_def_id: DefId, + method: &ty::AssocItem, + ) -> Option<MethodViolationCode> { // The method's first parameter must be named `self` if !method.method_has_self_argument { return Some(MethodViolationCode::StaticMethod); @@ -323,7 +322,9 @@ impl<'tcx> TyCtxt<'tcx> { .collect::<Vec<_>>() // Do a shallow visit so that `contains_illegal_self_type_reference` // may apply it's custom visiting. - .visit_tys_shallow(|t| self.contains_illegal_self_type_reference(trait_def_id, t)) { + .visit_tys_shallow(|t| { + self.contains_illegal_self_type_reference(trait_def_id, t) + }) { let span = self.def_span(method.def_id); return Some(MethodViolationCode::WhereClauseReferencesSelf(span)); } @@ -337,7 +338,7 @@ impl<'tcx> TyCtxt<'tcx> { // However, this is already considered object-safe. We allow it as a special case here. // FIXME(mikeyhew) get rid of this `if` statement once `receiver_is_dispatchable` allows // `Receiver: Unsize<Receiver[Self => dyn Trait]>` - if receiver_ty != self.mk_self_type() { + if receiver_ty != self.types.self_param { if !self.receiver_is_dispatchable(method, receiver_ty) { return Some(MethodViolationCode::UndispatchableReceiver); } else { @@ -404,7 +405,10 @@ impl<'tcx> TyCtxt<'tcx> { /// Performs a type substitution to produce the version of receiver_ty when `Self = self_ty` /// e.g., for receiver_ty = `Rc<Self>` and self_ty = `Foo`, returns `Rc<Foo>`. fn receiver_for_self_ty( - self, receiver_ty: Ty<'tcx>, self_ty: Ty<'tcx>, method_def_id: DefId + self, + receiver_ty: Ty<'tcx>, + self_ty: Ty<'tcx>, + method_def_id: DefId, ) -> Ty<'tcx> { debug!("receiver_for_self_ty({:?}, {:?}, {:?})", receiver_ty, self_ty, method_def_id); let substs = InternalSubsts::for_item(self, method_def_id, |param, _| { @@ -555,7 +559,7 @@ impl<'tcx> TyCtxt<'tcx> { // Self: Unsize<U> let unsize_predicate = ty::TraitRef { def_id: unsize_did, - substs: self.mk_substs_trait(self.mk_self_type(), &[unsized_self_ty.into()]), + substs: self.mk_substs_trait(self.types.self_param, &[unsized_self_ty.into()]), }.to_predicate(); // U: Trait<Arg1, ..., ArgN> @@ -608,11 +612,11 @@ impl<'tcx> TyCtxt<'tcx> { }) } - fn contains_illegal_self_type_reference(self, - trait_def_id: DefId, - ty: Ty<'tcx>) - -> bool - { + fn contains_illegal_self_type_reference( + self, + trait_def_id: DefId, + ty: Ty<'tcx>, + ) -> bool { // This is somewhat subtle. In general, we want to forbid // references to `Self` in the argument and return types, // since the value of `Self` is erased. However, there is one @@ -654,10 +658,11 @@ impl<'tcx> TyCtxt<'tcx> { let mut supertraits: Option<Vec<ty::PolyTraitRef<'tcx>>> = None; let mut error = false; + let self_ty = self.types.self_param; ty.maybe_walk(|ty| { match ty.sty { - ty::Param(ref param_ty) => { - if param_ty.is_self() { + ty::Param(_) => { + if ty == self_ty { error = true; } diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index 38263f26a59..72df45df923 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -1417,7 +1417,7 @@ fn confirm_callable_candidate<'cx, 'tcx>( projection_ty: ty::ProjectionTy::from_ref_and_name( tcx, trait_ref, - Ident::with_empty_ctxt(FN_OUTPUT_NAME), + Ident::with_dummy_span(FN_OUTPUT_NAME), ), ty: ret_type } diff --git a/src/librustc/ty/codec.rs b/src/librustc/ty/codec.rs index e3c6eca02d5..1ddc6780aca 100644 --- a/src/librustc/ty/codec.rs +++ b/src/librustc/ty/codec.rs @@ -27,7 +27,7 @@ pub trait EncodableWithShorthand: Clone + Eq + Hash { fn variant(&self) -> &Self::Variant; } -#[cfg_attr(not(bootstrap), allow(rustc::usage_of_ty_tykind))] +#[allow(rustc::usage_of_ty_tykind)] impl<'tcx> EncodableWithShorthand for Ty<'tcx> { type Variant = ty::TyKind<'tcx>; fn variant(&self) -> &Self::Variant { @@ -160,7 +160,7 @@ where Ok(decoder.map_encoded_cnum_to_current(cnum)) } -#[cfg_attr(not(bootstrap), allow(rustc::usage_of_ty_tykind))] +#[allow(rustc::usage_of_ty_tykind)] #[inline] pub fn decode_ty<D>(decoder: &mut D) -> Result<Ty<'tcx>, D::Error> where diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index ef74d9e5b28..e72efdb057a 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -130,7 +130,7 @@ impl<'tcx> CtxtInterners<'tcx> { } /// Intern a type - #[cfg_attr(not(bootstrap), allow(rustc::usage_of_ty_tykind))] + #[allow(rustc::usage_of_ty_tykind)] #[inline(never)] fn intern_ty(&self, st: TyKind<'tcx> @@ -173,6 +173,7 @@ pub struct CommonTypes<'tcx> { pub f32: Ty<'tcx>, pub f64: Ty<'tcx>, pub never: Ty<'tcx>, + pub self_param: Ty<'tcx>, pub err: Ty<'tcx>, /// Dummy type used for the `Self` of a `TraitRef` created for converting @@ -915,6 +916,10 @@ impl<'tcx> CommonTypes<'tcx> { u128: mk(Uint(ast::UintTy::U128)), f32: mk(Float(ast::FloatTy::F32)), f64: mk(Float(ast::FloatTy::F64)), + self_param: mk(ty::Param(ty::ParamTy { + index: 0, + name: kw::SelfUpper.as_interned_str(), + })), trait_object_dummy_self: mk(Infer(ty::FreshTy(0))), } @@ -2076,7 +2081,7 @@ impl<'tcx> Hash for Interned<'tcx, TyS<'tcx>> { } } -#[cfg_attr(not(bootstrap), allow(rustc::usage_of_ty_tykind))] +#[allow(rustc::usage_of_ty_tykind)] impl<'tcx> Borrow<TyKind<'tcx>> for Interned<'tcx, TyS<'tcx>> { fn borrow<'a>(&'a self) -> &'a TyKind<'tcx> { &self.0.sty @@ -2291,7 +2296,7 @@ impl<'tcx> TyCtxt<'tcx> { self.mk_fn_ptr(converted_sig) } - #[cfg_attr(not(bootstrap), allow(rustc::usage_of_ty_tykind))] + #[allow(rustc::usage_of_ty_tykind)] #[inline] pub fn mk_ty(&self, st: TyKind<'tcx>) -> Ty<'tcx> { self.interners.intern_ty(st) @@ -2566,10 +2571,6 @@ impl<'tcx> TyCtxt<'tcx> { }) } - #[inline] - pub fn mk_self_type(self) -> Ty<'tcx> { - self.mk_ty_param(0, kw::SelfUpper.as_interned_str()) - } pub fn mk_param_from_def(self, param: &ty::GenericParamDef) -> Kind<'tcx> { match param.kind { diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index 4a72794b61a..d6d17a67e01 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -239,13 +239,7 @@ impl<'tcx> ty::TyS<'tcx> { ty::Infer(ty::FreshFloatTy(_)) => "fresh floating-point type".into(), ty::Projection(_) => "associated type".into(), ty::UnnormalizedProjection(_) => "non-normalized associated type".into(), - ty::Param(ref p) => { - if p.is_self() { - "Self".into() - } else { - "type parameter".into() - } - } + ty::Param(_) => "type parameter".into(), ty::Opaque(..) => "opaque type".into(), ty::Error => "type error".into(), } diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index 411b18e043a..b2d74f963b0 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -1,5 +1,5 @@ use crate::ty::subst::{SubstsRef, UnpackedKind}; -use crate::ty::{self, Ty, TypeFlags, TypeFoldable, InferConst}; +use crate::ty::{self, Ty, TypeFlags, InferConst}; use crate::mir::interpret::ConstValue; #[derive(Debug)] @@ -18,7 +18,7 @@ impl FlagComputation { } } - #[cfg_attr(not(bootstrap), allow(rustc::usage_of_ty_tykind))] + #[allow(rustc::usage_of_ty_tykind)] pub fn for_sty(st: &ty::TyKind<'_>) -> FlagComputation { let mut result = FlagComputation::new(); result.add_sty(st); @@ -62,7 +62,7 @@ impl FlagComputation { } // otherwise, this binder captures nothing } - #[cfg_attr(not(bootstrap), allow(rustc::usage_of_ty_tykind))] + #[allow(rustc::usage_of_ty_tykind)] fn add_sty(&mut self, st: &ty::TyKind<'_>) { match st { &ty::Bool | @@ -86,13 +86,9 @@ impl FlagComputation { self.add_flags(TypeFlags::HAS_TY_ERR) } - &ty::Param(ref p) => { + &ty::Param(_) => { self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES); - if p.is_self() { - self.add_flags(TypeFlags::HAS_SELF); - } else { - self.add_flags(TypeFlags::HAS_PARAMS); - } + self.add_flags(TypeFlags::HAS_PARAMS); } &ty::Generator(_, ref substs, _) => { @@ -143,11 +139,6 @@ impl FlagComputation { } &ty::Projection(ref data) => { - // currently we can't normalize projections that - // include bound regions, so track those separately. - if !data.has_escaping_bound_vars() { - self.add_flags(TypeFlags::HAS_NORMALIZABLE_PROJECTION); - } self.add_flags(TypeFlags::HAS_PROJECTION); self.add_projection_ty(data); } @@ -243,7 +234,7 @@ impl FlagComputation { match c.val { ConstValue::Unevaluated(_, substs) => { self.add_substs(substs); - self.add_flags(TypeFlags::HAS_NORMALIZABLE_PROJECTION | TypeFlags::HAS_PROJECTION); + self.add_flags(TypeFlags::HAS_PROJECTION); }, ConstValue::Infer(infer) => { self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES | TypeFlags::HAS_CT_INFER); diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index ab7df8e4e84..4b30412b419 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -85,9 +85,6 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { fn has_param_types(&self) -> bool { self.has_type_flags(TypeFlags::HAS_PARAMS) } - fn has_self_ty(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_SELF) - } fn has_infer_types(&self) -> bool { self.has_type_flags(TypeFlags::HAS_TY_INFER) } diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 457d018f017..c71e1ea4e58 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -298,8 +298,9 @@ impl<'tcx> Instance<'tcx> { ) -> Option<Instance<'tcx>> { debug!("resolve(def_id={:?}, substs={:?})", def_id, substs); let fn_sig = tcx.fn_sig(def_id); - let is_vtable_shim = - fn_sig.inputs().skip_binder().len() > 0 && fn_sig.input(0).skip_binder().is_self(); + let is_vtable_shim = fn_sig.inputs().skip_binder().len() > 0 + && fn_sig.input(0).skip_binder().is_param(0) + && tcx.generics_of(def_id).has_self; if is_vtable_shim { debug!(" => associated item with unsizeable self: Self"); Some(Instance { diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 19c753bc304..8febcfd0754 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -1601,7 +1601,6 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // resulting from the final codegen session. if layout.ty.has_param_types() || - layout.ty.has_self_ty() || !self.param_env.caller_bounds.is_empty() { return; @@ -1767,7 +1766,7 @@ impl<'tcx> SizeSkeleton<'tcx> { let tail = tcx.struct_tail_erasing_lifetimes(pointee, param_env); match tail.sty { ty::Param(_) | ty::Projection(_) => { - debug_assert!(tail.has_param_types() || tail.has_self_ty()); + debug_assert!(tail.has_param_types()); Ok(SizeSkeleton::Pointer { non_zero, tail: tcx.erase_regions(&tail) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 9d563e290de..0b81f193df4 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -414,61 +414,53 @@ pub struct CReaderCacheKey { bitflags! { pub struct TypeFlags: u32 { const HAS_PARAMS = 1 << 0; - const HAS_SELF = 1 << 1; - const HAS_TY_INFER = 1 << 2; - const HAS_RE_INFER = 1 << 3; - const HAS_RE_PLACEHOLDER = 1 << 4; + const HAS_TY_INFER = 1 << 1; + const HAS_RE_INFER = 1 << 2; + const HAS_RE_PLACEHOLDER = 1 << 3; /// Does this have any `ReEarlyBound` regions? Used to /// determine whether substitition is required, since those /// represent regions that are bound in a `ty::Generics` and /// hence may be substituted. - const HAS_RE_EARLY_BOUND = 1 << 5; + const HAS_RE_EARLY_BOUND = 1 << 4; /// Does this have any region that "appears free" in the type? /// Basically anything but `ReLateBound` and `ReErased`. - const HAS_FREE_REGIONS = 1 << 6; + const HAS_FREE_REGIONS = 1 << 5; /// Is an error type reachable? - const HAS_TY_ERR = 1 << 7; - const HAS_PROJECTION = 1 << 8; + const HAS_TY_ERR = 1 << 6; + const HAS_PROJECTION = 1 << 7; // FIXME: Rename this to the actual property since it's used for generators too - const HAS_TY_CLOSURE = 1 << 9; + const HAS_TY_CLOSURE = 1 << 8; /// `true` if there are "names" of types and regions and so forth /// that are local to a particular fn - const HAS_FREE_LOCAL_NAMES = 1 << 10; + const HAS_FREE_LOCAL_NAMES = 1 << 9; /// Present if the type belongs in a local type context. /// Only set for Infer other than Fresh. - const KEEP_IN_LOCAL_TCX = 1 << 11; - - // Is there a projection that does not involve a bound region? - // Currently we can't normalize projections w/ bound regions. - const HAS_NORMALIZABLE_PROJECTION = 1 << 12; + const KEEP_IN_LOCAL_TCX = 1 << 10; /// Does this have any `ReLateBound` regions? Used to check /// if a global bound is safe to evaluate. - const HAS_RE_LATE_BOUND = 1 << 13; + const HAS_RE_LATE_BOUND = 1 << 11; - const HAS_TY_PLACEHOLDER = 1 << 14; + const HAS_TY_PLACEHOLDER = 1 << 12; - const HAS_CT_INFER = 1 << 15; - const HAS_CT_PLACEHOLDER = 1 << 16; + const HAS_CT_INFER = 1 << 13; + const HAS_CT_PLACEHOLDER = 1 << 14; const NEEDS_SUBST = TypeFlags::HAS_PARAMS.bits | - TypeFlags::HAS_SELF.bits | TypeFlags::HAS_RE_EARLY_BOUND.bits; /// Flags representing the nominal content of a type, /// computed by FlagsComputation. If you add a new nominal /// flag, it should be added here too. const NOMINAL_FLAGS = TypeFlags::HAS_PARAMS.bits | - TypeFlags::HAS_SELF.bits | TypeFlags::HAS_TY_INFER.bits | TypeFlags::HAS_RE_INFER.bits | - TypeFlags::HAS_CT_INFER.bits | TypeFlags::HAS_RE_PLACEHOLDER.bits | TypeFlags::HAS_RE_EARLY_BOUND.bits | TypeFlags::HAS_FREE_REGIONS.bits | @@ -479,11 +471,12 @@ bitflags! { TypeFlags::KEEP_IN_LOCAL_TCX.bits | TypeFlags::HAS_RE_LATE_BOUND.bits | TypeFlags::HAS_TY_PLACEHOLDER.bits | + TypeFlags::HAS_CT_INFER.bits | TypeFlags::HAS_CT_PLACEHOLDER.bits; } } -#[cfg_attr(not(bootstrap), allow(rustc::usage_of_ty_tykind))] +#[allow(rustc::usage_of_ty_tykind)] pub struct TyS<'tcx> { pub sty: TyKind<'tcx>, pub flags: TypeFlags, @@ -1734,7 +1727,6 @@ impl<'tcx> ParamEnv<'tcx> { if value.has_placeholders() || value.needs_infer() || value.has_param_types() - || value.has_self_ty() { ParamEnvAnd { param_env: self, diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs index 00871a1cbf2..8bf01970eb5 100644 --- a/src/librustc/ty/query/on_disk_cache.rs +++ b/src/librustc/ty/query/on_disk_cache.rs @@ -23,16 +23,16 @@ use std::mem; use syntax::ast::NodeId; use syntax::source_map::{SourceMap, StableSourceFileId}; use syntax_pos::{BytePos, Span, DUMMY_SP, SourceFile}; -use syntax_pos::hygiene::{ExpnId, SyntaxContext, ExpnInfo}; +use syntax_pos::hygiene::{ExpnId, SyntaxContext, ExpnData}; const TAG_FILE_FOOTER: u128 = 0xC0FFEE_C0FFEE_C0FFEE_C0FFEE_C0FFEE; const TAG_CLEAR_CROSS_CRATE_CLEAR: u8 = 0; const TAG_CLEAR_CROSS_CRATE_SET: u8 = 1; -const TAG_NO_EXPANSION_INFO: u8 = 0; -const TAG_EXPANSION_INFO_SHORTHAND: u8 = 1; -const TAG_EXPANSION_INFO_INLINE: u8 = 2; +const TAG_NO_EXPN_DATA: u8 = 0; +const TAG_EXPN_DATA_SHORTHAND: u8 = 1; +const TAG_EXPN_DATA_INLINE: u8 = 2; const TAG_VALID_SPAN: u8 = 0; const TAG_INVALID_SPAN: u8 = 1; @@ -58,7 +58,7 @@ pub struct OnDiskCache<'sess> { // These two fields caches that are populated lazily during decoding. file_index_to_file: Lock<FxHashMap<SourceFileIndex, Lrc<SourceFile>>>, - synthetic_expansion_infos: Lock<FxHashMap<AbsoluteBytePos, SyntaxContext>>, + synthetic_syntax_contexts: Lock<FxHashMap<AbsoluteBytePos, SyntaxContext>>, // A map from dep-node to the position of the cached query result in // `serialized_data`. @@ -135,7 +135,7 @@ impl<'sess> OnDiskCache<'sess> { current_diagnostics: Default::default(), query_result_index: footer.query_result_index.into_iter().collect(), prev_diagnostics_index: footer.diagnostics_index.into_iter().collect(), - synthetic_expansion_infos: Default::default(), + synthetic_syntax_contexts: Default::default(), alloc_decoding_state: AllocDecodingState::new(footer.interpret_alloc_index), } } @@ -151,7 +151,7 @@ impl<'sess> OnDiskCache<'sess> { current_diagnostics: Default::default(), query_result_index: Default::default(), prev_diagnostics_index: Default::default(), - synthetic_expansion_infos: Default::default(), + synthetic_syntax_contexts: Default::default(), alloc_decoding_state: AllocDecodingState::new(Vec::new()), } } @@ -185,7 +185,7 @@ impl<'sess> OnDiskCache<'sess> { encoder, type_shorthands: Default::default(), predicate_shorthands: Default::default(), - expn_info_shorthands: Default::default(), + expn_data_shorthands: Default::default(), interpret_allocs: Default::default(), interpret_allocs_inverse: Vec::new(), source_map: CachingSourceMapView::new(tcx.sess.source_map()), @@ -383,7 +383,7 @@ impl<'sess> OnDiskCache<'sess> { cnum_map: self.cnum_map.get(), file_index_to_file: &self.file_index_to_file, file_index_to_stable_id: &self.file_index_to_stable_id, - synthetic_expansion_infos: &self.synthetic_expansion_infos, + synthetic_syntax_contexts: &self.synthetic_syntax_contexts, alloc_decoding_session: self.alloc_decoding_state.new_decoding_session(), }; @@ -440,7 +440,7 @@ struct CacheDecoder<'a, 'tcx> { opaque: opaque::Decoder<'a>, source_map: &'a SourceMap, cnum_map: &'a IndexVec<CrateNum, Option<CrateNum>>, - synthetic_expansion_infos: &'a Lock<FxHashMap<AbsoluteBytePos, SyntaxContext>>, + synthetic_syntax_contexts: &'a Lock<FxHashMap<AbsoluteBytePos, SyntaxContext>>, file_index_to_file: &'a Lock<FxHashMap<SourceFileIndex, Lrc<SourceFile>>>, file_index_to_stable_id: &'a FxHashMap<SourceFileIndex, StableSourceFileId>, alloc_decoding_session: AllocDecodingSession<'a>, @@ -586,37 +586,37 @@ impl<'a, 'tcx> SpecializedDecoder<Span> for CacheDecoder<'a, 'tcx> { let lo = file_lo.lines[line_lo - 1] + col_lo; let hi = lo + len; - let expn_info_tag = u8::decode(self)?; + let expn_data_tag = u8::decode(self)?; - // FIXME(mw): This method does not restore `InternalExpnData::parent` or + // FIXME(mw): This method does not restore `ExpnData::parent` or // `SyntaxContextData::prev_ctxt` or `SyntaxContextData::opaque`. These things // don't seem to be used after HIR lowering, so everything should be fine // as long as incremental compilation does not kick in before that. - let location = || Span::new(lo, hi, SyntaxContext::empty()); - let recover_from_expn_info = |this: &Self, expn_info, pos| { - let span = location().fresh_expansion(ExpnId::root(), expn_info); - this.synthetic_expansion_infos.borrow_mut().insert(pos, span.ctxt()); + let location = || Span::with_root_ctxt(lo, hi); + let recover_from_expn_data = |this: &Self, expn_data, pos| { + let span = location().fresh_expansion(expn_data); + this.synthetic_syntax_contexts.borrow_mut().insert(pos, span.ctxt()); span }; - Ok(match expn_info_tag { - TAG_NO_EXPANSION_INFO => { + Ok(match expn_data_tag { + TAG_NO_EXPN_DATA => { location() } - TAG_EXPANSION_INFO_INLINE => { - let expn_info = Decodable::decode(self)?; - recover_from_expn_info( - self, expn_info, AbsoluteBytePos::new(self.opaque.position()) + TAG_EXPN_DATA_INLINE => { + let expn_data = Decodable::decode(self)?; + recover_from_expn_data( + self, expn_data, AbsoluteBytePos::new(self.opaque.position()) ) } - TAG_EXPANSION_INFO_SHORTHAND => { + TAG_EXPN_DATA_SHORTHAND => { let pos = AbsoluteBytePos::decode(self)?; - let cached_ctxt = self.synthetic_expansion_infos.borrow().get(&pos).cloned(); + let cached_ctxt = self.synthetic_syntax_contexts.borrow().get(&pos).cloned(); if let Some(ctxt) = cached_ctxt { Span::new(lo, hi, ctxt) } else { - let expn_info = - self.with_position(pos.to_usize(), |this| ExpnInfo::decode(this))?; - recover_from_expn_info(self, expn_info, pos) + let expn_data = + self.with_position(pos.to_usize(), |this| ExpnData::decode(this))?; + recover_from_expn_data(self, expn_data, pos) } } _ => { @@ -725,7 +725,7 @@ struct CacheEncoder<'a, 'tcx, E: ty_codec::TyEncoder> { encoder: &'a mut E, type_shorthands: FxHashMap<Ty<'tcx>, usize>, predicate_shorthands: FxHashMap<ty::Predicate<'tcx>, usize>, - expn_info_shorthands: FxHashMap<ExpnId, AbsoluteBytePos>, + expn_data_shorthands: FxHashMap<ExpnId, AbsoluteBytePos>, interpret_allocs: FxHashMap<interpret::AllocId, usize>, interpret_allocs_inverse: Vec<interpret::AllocId>, source_map: CachingSourceMapView<'tcx>, @@ -816,22 +816,18 @@ where col_lo.encode(self)?; len.encode(self)?; - if span_data.ctxt == SyntaxContext::empty() { - TAG_NO_EXPANSION_INFO.encode(self) + if span_data.ctxt == SyntaxContext::root() { + TAG_NO_EXPN_DATA.encode(self) } else { - let (expn_id, expn_info) = span_data.ctxt.outer_expn_with_info(); - if let Some(expn_info) = expn_info { - if let Some(pos) = self.expn_info_shorthands.get(&expn_id).cloned() { - TAG_EXPANSION_INFO_SHORTHAND.encode(self)?; - pos.encode(self) - } else { - TAG_EXPANSION_INFO_INLINE.encode(self)?; - let pos = AbsoluteBytePos::new(self.position()); - self.expn_info_shorthands.insert(expn_id, pos); - expn_info.encode(self) - } + let (expn_id, expn_data) = span_data.ctxt.outer_expn_with_data(); + if let Some(pos) = self.expn_data_shorthands.get(&expn_id).cloned() { + TAG_EXPN_DATA_SHORTHAND.encode(self)?; + pos.encode(self) } else { - TAG_NO_EXPANSION_INFO.encode(self) + TAG_EXPN_DATA_INLINE.encode(self)?; + let pos = AbsoluteBytePos::new(self.position()); + self.expn_data_shorthands.insert(expn_id, pos); + expn_data.encode(self) } } } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 129ea9b5b67..2b173068b38 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -1,6 +1,6 @@ //! This module contains `TyKind` and its major components. -#![cfg_attr(not(bootstrap), allow(rustc::usage_of_ty_tykind))] +#![allow(rustc::usage_of_ty_tykind)] use crate::hir; use crate::hir::def_id::DefId; @@ -1141,13 +1141,6 @@ impl<'tcx> ParamTy { pub fn to_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { tcx.mk_ty_param(self.index, self.name) } - - pub fn is_self(&self) -> bool { - // FIXME(#50125): Ignoring `Self` with `index != 0` might lead to weird behavior elsewhere, - // but this should only be possible when using `-Z continue-parse-after-error` like - // `compile-fail/issue-36638.rs`. - self.name.as_symbol() == kw::SelfUpper && self.index == 0 - } } #[derive(Copy, Clone, Hash, RustcEncodable, RustcDecodable, @@ -1790,14 +1783,6 @@ impl<'tcx> TyS<'tcx> { } #[inline] - pub fn is_self(&self) -> bool { - match self.sty { - Param(ref p) => p.is_self(), - _ => false, - } - } - - #[inline] pub fn is_slice(&self) -> bool { match self.sty { RawPtr(TypeAndMut { ty, .. }) | Ref(_, ty, _) => match ty.sty { @@ -2068,6 +2053,9 @@ impl<'tcx> TyS<'tcx> { Error => { // ignore errors (#54954) ty::Binder::dummy(FnSig::fake()) } + Closure(..) => bug!( + "to get the signature of a closure, use `closure_sig()` not `fn_sig()`", + ), _ => bug!("Ty::fn_sig() called on non-fn type: {:?}", self) } } diff --git a/src/librustc_codegen_llvm/asm.rs b/src/librustc_codegen_llvm/asm.rs index 9763d523a2a..b68ee2cb44d 100644 --- a/src/librustc_codegen_llvm/asm.rs +++ b/src/librustc_codegen_llvm/asm.rs @@ -6,9 +6,9 @@ use crate::value::Value; use rustc::hir; use rustc_codegen_ssa::traits::*; - use rustc_codegen_ssa::mir::place::PlaceRef; use rustc_codegen_ssa::mir::operand::OperandValue; +use syntax_pos::Span; use std::ffi::{CStr, CString}; use libc::{c_uint, c_char}; @@ -19,7 +19,8 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { &mut self, ia: &hir::InlineAsm, outputs: Vec<PlaceRef<'tcx, &'ll Value>>, - mut inputs: Vec<&'ll Value> + mut inputs: Vec<&'ll Value>, + span: Span, ) -> bool { let mut ext_constraints = vec![]; let mut output_types = vec![]; @@ -102,7 +103,7 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { let kind = llvm::LLVMGetMDKindIDInContext(self.llcx, key.as_ptr() as *const c_char, key.len() as c_uint); - let val: &'ll Value = self.const_i32(ia.ctxt.outer_expn().as_u32() as i32); + let val: &'ll Value = self.const_i32(span.ctxt().outer_expn().as_u32() as i32); llvm::LLVMSetMetadata(r, kind, llvm::LLVMMDNodeInContext(self.llcx, &val, 1)); diff --git a/src/librustc_codegen_llvm/common.rs b/src/librustc_codegen_llvm/common.rs index b0c94a139be..19f18088579 100644 --- a/src/librustc_codegen_llvm/common.rs +++ b/src/librustc_codegen_llvm/common.rs @@ -333,15 +333,21 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { offset: Size, ) -> PlaceRef<'tcx, &'ll Value> { assert_eq!(alloc.align, layout.align.abi); - let init = const_alloc_to_llvm(self, alloc); - let base_addr = self.static_addr_of(init, alloc.align, None); - - let llval = unsafe { llvm::LLVMConstInBoundsGEP( - self.const_bitcast(base_addr, self.type_i8p()), - &self.const_usize(offset.bytes()), - 1, - )}; - let llval = self.const_bitcast(llval, self.type_ptr_to(layout.llvm_type(self))); + let llty = self.type_ptr_to(layout.llvm_type(self)); + let llval = if layout.size == Size::ZERO { + let llval = self.const_usize(alloc.align.bytes()); + unsafe { llvm::LLVMConstIntToPtr(llval, llty) } + } else { + let init = const_alloc_to_llvm(self, alloc); + let base_addr = self.static_addr_of(init, alloc.align, None); + + let llval = unsafe { llvm::LLVMConstInBoundsGEP( + self.const_bitcast(base_addr, self.type_i8p()), + &self.const_usize(offset.bytes()), + 1, + )}; + self.const_bitcast(llval, llty) + }; PlaceRef::new_sized(llval, layout, alloc.align) } diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index a9b8962f45b..9483ffca448 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -328,7 +328,7 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { }, "ctlz" | "ctlz_nonzero" | "cttz" | "cttz_nonzero" | "ctpop" | "bswap" | "bitreverse" | "add_with_overflow" | "sub_with_overflow" | - "mul_with_overflow" | "overflowing_add" | "overflowing_sub" | "overflowing_mul" | + "mul_with_overflow" | "wrapping_add" | "wrapping_sub" | "wrapping_mul" | "unchecked_div" | "unchecked_rem" | "unchecked_shl" | "unchecked_shr" | "unchecked_add" | "unchecked_sub" | "unchecked_mul" | "exact_div" | "rotate_left" | "rotate_right" | "saturating_add" | "saturating_sub" => { @@ -398,9 +398,9 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { return; }, - "overflowing_add" => self.add(args[0].immediate(), args[1].immediate()), - "overflowing_sub" => self.sub(args[0].immediate(), args[1].immediate()), - "overflowing_mul" => self.mul(args[0].immediate(), args[1].immediate()), + "wrapping_add" => self.add(args[0].immediate(), args[1].immediate()), + "wrapping_sub" => self.sub(args[0].immediate(), args[1].immediate()), + "wrapping_mul" => self.mul(args[0].immediate(), args[1].immediate()), "exact_div" => if signed { self.exactsdiv(args[0].immediate(), args[1].immediate()) diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index 8fb0828285c..8603d61fb54 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -32,6 +32,7 @@ use std::path::{Path, PathBuf}; use std::process::{Output, Stdio, ExitStatus}; use std::str; use std::env; +use std::ffi::OsString; pub use rustc_codegen_utils::link::*; @@ -158,6 +159,36 @@ pub fn get_linker(sess: &Session, linker: &Path, flavor: LinkerFlavor) -> (PathB } }; + // UWP apps have API restrictions enforced during Store submissions. + // To comply with the Windows App Certification Kit, + // MSVC needs to link with the Store versions of the runtime libraries (vcruntime, msvcrt, etc). + let t = &sess.target.target; + if flavor == LinkerFlavor::Msvc && t.target_vendor == "uwp" { + if let Some(ref tool) = msvc_tool { + let original_path = tool.path(); + if let Some(ref root_lib_path) = original_path.ancestors().skip(4).next() { + let arch = match t.arch.as_str() { + "x86_64" => Some("x64".to_string()), + "x86" => Some("x86".to_string()), + "aarch64" => Some("arm64".to_string()), + _ => None, + }; + if let Some(ref a) = arch { + let mut arg = OsString::from("/LIBPATH:"); + arg.push(format!("{}\\lib\\{}\\store", root_lib_path.display(), a.to_string())); + cmd.arg(&arg); + } + else { + warn!("arch is not supported"); + } + } else { + warn!("MSVC root path lib location not found"); + } + } else { + warn!("link.exe not found"); + } + } + // The compiler's sysroot often has some bundled tools, so add it to the // PATH for the child. let mut new_path = sess.host_filesearch(PathKind::All) @@ -1027,6 +1058,7 @@ fn link_args<'a, B: ArchiveBuilder<'a>>(cmd: &mut dyn Linker, let t = &sess.target.target; cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path)); + for obj in codegen_results.modules.iter().filter_map(|m| m.object.as_ref()) { cmd.add_object(obj); } diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index c9e4663fdbd..eec09842623 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -1775,10 +1775,7 @@ impl SharedEmitterMain { } } Ok(SharedEmitterMessage::InlineAsmError(cookie, msg)) => { - match ExpnId::from_u32(cookie).expn_info() { - Some(ei) => sess.span_err(ei.call_site, &msg), - None => sess.err(&msg), - } + sess.span_err(ExpnId::from_u32(cookie).expn_data().call_site, &msg) } Ok(SharedEmitterMessage::AbortIfErrors) => { sess.abort_if_errors(); diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs index cc0c733c224..e63f1b91dd7 100644 --- a/src/librustc_codegen_ssa/mir/analyze.rs +++ b/src/librustc_codegen_ssa/mir/analyze.rs @@ -221,7 +221,7 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx> mir::TerminatorKind::Call { func: mir::Operand::Constant(ref c), ref args, .. - } => match c.ty.sty { + } => match c.literal.ty.sty { ty::FnDef(did, _) => Some((did, args)), _ => None, }, diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index ce98979cc0c..dbce5ce4896 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -651,7 +651,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let (llval, ty) = self.simd_shuffle_indices( &bx, constant.span, - constant.ty, + constant.literal.ty, c, ); return OperandRef { diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs index e7517d69991..32bcdebc1c4 100644 --- a/src/librustc_codegen_ssa/mir/mod.rs +++ b/src/librustc_codegen_ssa/mir/mod.rs @@ -8,7 +8,7 @@ use crate::base; use crate::debuginfo::{self, VariableAccess, VariableKind, FunctionDebugContext}; use crate::traits::*; -use syntax_pos::{DUMMY_SP, NO_EXPANSION, BytePos, Span}; +use syntax_pos::{DUMMY_SP, BytePos, Span}; use syntax::symbol::kw; use std::iter; @@ -120,7 +120,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // In order to have a good line stepping behavior in debugger, we overwrite debug // locations of macro expansions with that of the outermost expansion site // (unless the crate is being compiled with `-Z debug-macros`). - if source_info.span.ctxt() == NO_EXPANSION || + if !source_info.span.from_expansion() || self.cx.sess().opts.debugging_opts.debug_macros { let scope = self.scope_metadata_for_loc(source_info.scope, source_info.span.lo()); (scope, source_info.span) diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs index 5e5804b7265..254b73da442 100644 --- a/src/librustc_codegen_ssa/mir/operand.rs +++ b/src/librustc_codegen_ssa/mir/operand.rs @@ -466,7 +466,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } mir::Operand::Constant(ref constant) => { - let ty = self.monomorphize(&constant.ty); self.eval_mir_constant(constant) .map(|c| OperandRef::from_const(bx, c)) .unwrap_or_else(|err| { @@ -481,6 +480,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // the above error (or silence it under some conditions) will not cause UB bx.abort(); // We've errored, so we don't have to produce working code. + let ty = self.monomorphize(&constant.literal.ty); let layout = bx.cx().layout_of(ty); bx.load_operand(PlaceRef::new_sized( bx.cx().const_undef(bx.cx().type_ptr_to(bx.cx().backend_type(layout))), diff --git a/src/librustc_codegen_ssa/mir/statement.rs b/src/librustc_codegen_ssa/mir/statement.rs index 3717be4b417..3617f3afaae 100644 --- a/src/librustc_codegen_ssa/mir/statement.rs +++ b/src/librustc_codegen_ssa/mir/statement.rs @@ -89,7 +89,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }); if input_vals.len() == asm.inputs.len() { - let res = bx.codegen_inline_asm(&asm.asm, outputs, input_vals); + let res = bx.codegen_inline_asm( + &asm.asm, + outputs, + input_vals, + statement.source_info.span, + ); if !res { span_err!(bx.sess(), statement.source_info.span, E0668, "malformed inline assembly"); diff --git a/src/librustc_codegen_ssa/traits/asm.rs b/src/librustc_codegen_ssa/traits/asm.rs index fd3c868bbc5..c9e1ed86e97 100644 --- a/src/librustc_codegen_ssa/traits/asm.rs +++ b/src/librustc_codegen_ssa/traits/asm.rs @@ -1,6 +1,7 @@ use super::BackendTypes; use crate::mir::place::PlaceRef; use rustc::hir::{GlobalAsm, InlineAsm}; +use syntax_pos::Span; pub trait AsmBuilderMethods<'tcx>: BackendTypes { /// Take an inline assembly expression and splat it out via LLVM @@ -9,6 +10,7 @@ pub trait AsmBuilderMethods<'tcx>: BackendTypes { ia: &InlineAsm, outputs: Vec<PlaceRef<'tcx, Self::Value>>, inputs: Vec<Self::Value>, + span: Span, ) -> bool; } diff --git a/src/librustc_codegen_utils/Cargo.toml b/src/librustc_codegen_utils/Cargo.toml index d93589ea84b..89b50c5dacc 100644 --- a/src/librustc_codegen_utils/Cargo.toml +++ b/src/librustc_codegen_utils/Cargo.toml @@ -13,7 +13,7 @@ test = false flate2 = "1.0" log = "0.4" punycode = "0.4.0" -rustc-demangle = "0.1.15" +rustc-demangle = "0.1.16" syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/librustc_codegen_utils/symbol_names/v0.rs b/src/librustc_codegen_utils/symbol_names/v0.rs index 47601da8b7b..8d6a1d757e0 100644 --- a/src/librustc_codegen_utils/symbol_names/v0.rs +++ b/src/librustc_codegen_utils/symbol_names/v0.rs @@ -198,10 +198,14 @@ impl SymbolMangler<'tcx> { let lifetimes = regions.into_iter().map(|br| { match br { - ty::BrAnon(i) => i + 1, + ty::BrAnon(i) => { + // FIXME(eddyb) for some reason, `anonymize_late_bound_regions` starts at `1`. + assert_ne!(i, 0); + i - 1 + }, _ => bug!("symbol_names: non-anonymized region `{:?}` in `{:?}`", br, value), } - }).max().unwrap_or(0); + }).max().map_or(0, |max| max + 1); self.push_opt_integer_62("G", lifetimes as u64); lifetime_depths.end += lifetimes; @@ -297,6 +301,10 @@ impl Printer<'tcx> for SymbolMangler<'tcx> { // Late-bound lifetimes use indices starting at 1, // see `BinderLevel` for more details. ty::ReLateBound(debruijn, ty::BrAnon(i)) => { + // FIXME(eddyb) for some reason, `anonymize_late_bound_regions` starts at `1`. + assert_ne!(i, 0); + let i = i - 1; + let binder = &self.binders[self.binders.len() - 1 - debruijn.index()]; let depth = binder.lifetime_depths.start + i; diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index 9f103437d36..f7593501959 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -27,7 +27,7 @@ #![cfg_attr(unix, feature(libc))] -#![cfg_attr(not(bootstrap), allow(rustc::default_hash_types))] +#![allow(rustc::default_hash_types)] #[macro_use] extern crate log; diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml index 42aa8203cba..b030517e28e 100644 --- a/src/librustc_driver/Cargo.toml +++ b/src/librustc_driver/Cargo.toml @@ -20,6 +20,8 @@ rustc_data_structures = { path = "../librustc_data_structures" } errors = { path = "../librustc_errors", package = "rustc_errors" } rustc_metadata = { path = "../librustc_metadata" } rustc_mir = { path = "../librustc_mir" } +rustc_plugin = { path = "../librustc_plugin/deprecated" } # To get this in the sysroot +rustc_plugin_impl = { path = "../librustc_plugin" } rustc_save_analysis = { path = "../librustc_save_analysis" } rustc_codegen_utils = { path = "../librustc_codegen_utils" } rustc_interface = { path = "../librustc_interface" } diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index e9d85a53d1e..b19ea513b75 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -22,6 +22,8 @@ extern crate libc; #[macro_use] extern crate log; +pub extern crate rustc_plugin_impl as plugin; + use pretty::{PpMode, UserIdentifiedItem}; //use rustc_resolve as resolve; @@ -678,7 +680,7 @@ impl RustcDefaultCalls { let mut cfgs = sess.parse_sess.config.iter().filter_map(|&(name, ref value)| { let gated_cfg = GatedCfg::gate(&ast::MetaItem { - path: ast::Path::from_ident(ast::Ident::with_empty_ctxt(name)), + path: ast::Path::from_ident(ast::Ident::with_dummy_span(name)), node: ast::MetaItemKind::Word, span: DUMMY_SP, }); diff --git a/src/librustc_errors/annotate_snippet_emitter_writer.rs b/src/librustc_errors/annotate_snippet_emitter_writer.rs index 96a9b6c5c4f..255af3122e7 100644 --- a/src/librustc_errors/annotate_snippet_emitter_writer.rs +++ b/src/librustc_errors/annotate_snippet_emitter_writer.rs @@ -148,7 +148,7 @@ impl<'a> DiagnosticConverter<'a> { /// Maps `Diagnostic::Level` to `snippet::AnnotationType` fn annotation_type_for_level(level: Level) -> AnnotationType { match level { - Level::Bug | Level::Fatal | Level::PhaseFatal | Level::Error => AnnotationType::Error, + Level::Bug | Level::Fatal | Level::Error => AnnotationType::Error, Level::Warning => AnnotationType::Warning, Level::Note => AnnotationType::Note, Level::Help => AnnotationType::Help, diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs index 424d7c00383..3f1b91256c4 100644 --- a/src/librustc_errors/diagnostic.rs +++ b/src/librustc_errors/diagnostic.rs @@ -94,7 +94,6 @@ impl Diagnostic { match self.level { Level::Bug | Level::Fatal | - Level::PhaseFatal | Level::Error | Level::FailureNote => { true @@ -120,6 +119,9 @@ impl Diagnostic { } /// Adds a span/label to be included in the resulting snippet. + /// This label will be shown together with the original span/label used when creating the + /// diagnostic, *not* a span added by one of the `span_*` methods. + /// /// This is pushed onto the `MultiSpan` that was created when the /// diagnostic was first built. If you don't call this function at /// all, and you just supplied a `Span` to create the diagnostic, @@ -196,6 +198,7 @@ impl Diagnostic { self } + /// Prints the span with a note above it. pub fn span_note<S: Into<MultiSpan>>(&mut self, sp: S, msg: &str) @@ -209,6 +212,7 @@ impl Diagnostic { self } + /// Prints the span with a warn above it. pub fn span_warn<S: Into<MultiSpan>>(&mut self, sp: S, msg: &str) @@ -222,6 +226,7 @@ impl Diagnostic { self } + /// Prints the span with some help above it. pub fn span_help<S: Into<MultiSpan>>(&mut self, sp: S, msg: &str) diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index 3b6a6a824c8..4018a667bf2 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -43,8 +43,7 @@ use syntax_pos::{BytePos, SourceFile, FileName, MultiSpan, - Span, - NO_EXPANSION}; + Span}; /// Indicates the confidence in the correctness of a suggestion. /// @@ -189,7 +188,7 @@ impl CodeSuggestion { // Find the bounding span. let lo = substitution.parts.iter().map(|part| part.span.lo()).min().unwrap(); let hi = substitution.parts.iter().map(|part| part.span.hi()).min().unwrap(); - let bounding_span = Span::new(lo, hi, NO_EXPANSION); + let bounding_span = Span::with_root_ctxt(lo, hi); let lines = cm.span_to_lines(bounding_span).unwrap(); assert!(!lines.lines.is_empty()); @@ -787,9 +786,6 @@ impl Handler { pub enum Level { Bug, Fatal, - // An error which while not immediately fatal, should stop the compiler - // progressing beyond the current phase. - PhaseFatal, Error, Warning, Note, @@ -808,7 +804,7 @@ impl Level { fn color(self) -> ColorSpec { let mut spec = ColorSpec::new(); match self { - Bug | Fatal | PhaseFatal | Error => { + Bug | Fatal | Error => { spec.set_fg(Some(Color::Red)) .set_intense(true); } @@ -833,7 +829,7 @@ impl Level { pub fn to_str(self) -> &'static str { match self { Bug => "error: internal compiler error", - Fatal | PhaseFatal | Error => "error", + Fatal | Error => "error", Warning => "warning", Note => "note", Help => "help", diff --git a/src/librustc_interface/Cargo.toml b/src/librustc_interface/Cargo.toml index 4937801d311..16b377d5bcc 100644 --- a/src/librustc_interface/Cargo.toml +++ b/src/librustc_interface/Cargo.toml @@ -30,7 +30,7 @@ rustc_passes = { path = "../librustc_passes" } rustc_typeck = { path = "../librustc_typeck" } rustc_lint = { path = "../librustc_lint" } rustc_errors = { path = "../librustc_errors" } -rustc_plugin = { path = "../librustc_plugin" } +rustc_plugin = { path = "../librustc_plugin", package = "rustc_plugin_impl" } rustc_privacy = { path = "../librustc_privacy" } rustc_resolve = { path = "../librustc_resolve" } tempfile = "3.0.5" diff --git a/src/librustc_lexer/src/lib.rs b/src/librustc_lexer/src/lib.rs index c02abe6b89f..41b47befaf1 100644 --- a/src/librustc_lexer/src/lib.rs +++ b/src/librustc_lexer/src/lib.rs @@ -23,9 +23,6 @@ pub enum TokenKind { Lifetime { starts_with_number: bool }, Semi, Comma, - DotDotDot, - DotDotEq, - DotDot, Dot, OpenParen, CloseParen, @@ -37,41 +34,19 @@ pub enum TokenKind { Pound, Tilde, Question, - ColonColon, Colon, Dollar, - EqEq, Eq, - FatArrow, - Ne, Not, - Le, - LArrow, Lt, - ShlEq, - Shl, - Ge, Gt, - ShrEq, - Shr, - RArrow, Minus, - MinusEq, And, - AndAnd, - AndEq, Or, - OrOr, - OrEq, - PlusEq, Plus, - StarEq, Star, - SlashEq, Slash, - CaretEq, Caret, - PercentEq, Percent, Unknown, } @@ -135,13 +110,7 @@ impl Cursor<'_> { '/' => match self.nth_char(0) { '/' => self.line_comment(), '*' => self.block_comment(), - _ => { - if self.eat_assign() { - SlashEq - } else { - Slash - } - } + _ => Slash, }, c if character_properties::is_whitespace(c) => self.whitespace(), 'r' => match (self.nth_char(0), self.nth_char(1)) { @@ -199,22 +168,7 @@ impl Cursor<'_> { } ';' => Semi, ',' => Comma, - '.' => { - if self.nth_char(0) == '.' { - self.bump(); - if self.nth_char(0) == '.' { - self.bump(); - DotDotDot - } else if self.nth_char(0) == '=' { - self.bump(); - DotDotEq - } else { - DotDot - } - } else { - Dot - } - } + '.' => Dot, '(' => OpenParen, ')' => CloseParen, '{' => OpenBrace, @@ -225,112 +179,19 @@ impl Cursor<'_> { '#' => Pound, '~' => Tilde, '?' => Question, - ':' => { - if self.nth_char(0) == ':' { - self.bump(); - ColonColon - } else { - Colon - } - } + ':' => Colon, '$' => Dollar, - '=' => { - if self.nth_char(0) == '=' { - self.bump(); - EqEq - } else if self.nth_char(0) == '>' { - self.bump(); - FatArrow - } else { - Eq - } - } - '!' => { - if self.nth_char(0) == '=' { - self.bump(); - Ne - } else { - Not - } - } - '<' => match self.nth_char(0) { - '=' => { - self.bump(); - Le - } - '<' => { - self.bump(); - if self.eat_assign() { ShlEq } else { Shl } - } - '-' => { - self.bump(); - LArrow - } - _ => Lt, - }, - '>' => match self.nth_char(0) { - '=' => { - self.bump(); - Ge - } - '>' => { - self.bump(); - if self.eat_assign() { ShrEq } else { Shr } - } - _ => Gt, - }, - '-' => { - if self.nth_char(0) == '>' { - self.bump(); - RArrow - } else { - if self.eat_assign() { MinusEq } else { Minus } - } - } - '&' => { - if self.nth_char(0) == '&' { - self.bump(); - AndAnd - } else { - if self.eat_assign() { AndEq } else { And } - } - } - '|' => { - if self.nth_char(0) == '|' { - self.bump(); - OrOr - } else { - if self.eat_assign() { OrEq } else { Or } - } - } - '+' => { - if self.eat_assign() { - PlusEq - } else { - Plus - } - } - '*' => { - if self.eat_assign() { - StarEq - } else { - Star - } - } - '^' => { - if self.eat_assign() { - CaretEq - } else { - Caret - } - } - '%' => { - if self.eat_assign() { - PercentEq - } else { - Percent - } - } + '=' => Eq, + '!' => Not, + '<' => Lt, + '>' => Gt, + '-' => Minus, + '&' => And, + '|' => Or, + '+' => Plus, + '*' => Star, + '^' => Caret, + '%' => Percent, '\'' => self.lifetime_or_char(), '"' => { let terminated = self.double_quoted_string(); @@ -352,7 +213,6 @@ impl Cursor<'_> { loop { match self.nth_char(0) { '\n' => break, - '\r' if self.nth_char(1) == '\n' => break, EOF_CHAR if self.is_eof() => break, _ => { self.bump(); @@ -525,7 +385,6 @@ impl Cursor<'_> { match self.nth_char(0) { '/' if !first => break, '\n' if self.nth_char(1) != '\'' => break, - '\r' if self.nth_char(1) == '\n' => break, EOF_CHAR if self.is_eof() => break, '\'' => { self.bump(); @@ -645,15 +504,6 @@ impl Cursor<'_> { self.bump(); } } - - fn eat_assign(&mut self) -> bool { - if self.nth_char(0) == '=' { - self.bump(); - true - } else { - false - } - } } pub mod character_properties { diff --git a/src/librustc_lexer/src/unescape.rs b/src/librustc_lexer/src/unescape.rs index d8e00d4c7c5..c709b752608 100644 --- a/src/librustc_lexer/src/unescape.rs +++ b/src/librustc_lexer/src/unescape.rs @@ -128,11 +128,7 @@ fn scan_escape(first_char: char, chars: &mut Chars<'_>, mode: Mode) -> Result<ch if first_char != '\\' { return match first_char { '\t' | '\n' => Err(EscapeError::EscapeOnlyChar), - '\r' => Err(if chars.clone().next() == Some('\n') { - EscapeError::EscapeOnlyChar - } else { - EscapeError::BareCarriageReturn - }), + '\r' => Err(EscapeError::BareCarriageReturn), '\'' if mode.in_single_quotes() => Err(EscapeError::EscapeOnlyChar), '"' if mode.in_double_quotes() => Err(EscapeError::EscapeOnlyChar), _ => { @@ -244,27 +240,15 @@ where let unescaped_char = match first_char { '\\' => { - let (second_char, third_char) = { - let mut chars = chars.clone(); - (chars.next(), chars.next()) - }; - match (second_char, third_char) { - (Some('\n'), _) | (Some('\r'), Some('\n')) => { + let second_char = chars.clone().next(); + match second_char { + Some('\n') => { skip_ascii_whitespace(&mut chars); continue; } _ => scan_escape(first_char, &mut chars, mode), } } - '\r' => { - let second_char = chars.clone().next(); - if second_char == Some('\n') { - chars.next(); - Ok('\n') - } else { - scan_escape(first_char, &mut chars, mode) - } - } '\n' => Ok('\n'), '\t' => Ok('\t'), _ => scan_escape(first_char, &mut chars, mode), @@ -298,15 +282,11 @@ where while let Some(curr) = chars.next() { let start = initial_len - chars.as_str().len() - curr.len_utf8(); - let result = match (curr, chars.clone().next()) { - ('\r', Some('\n')) => { - chars.next(); - Ok('\n') - }, - ('\r', _) => Err(EscapeError::BareCarriageReturnInRawString), - (c, _) if mode.is_bytes() && !c.is_ascii() => + let result = match curr { + '\r' => Err(EscapeError::BareCarriageReturnInRawString), + c if mode.is_bytes() && !c.is_ascii() => Err(EscapeError::NonAsciiCharInByteString), - (c, _) => Ok(c), + c => Ok(c), }; let end = initial_len - chars.as_str().len(); diff --git a/src/librustc_lexer/src/unescape/tests.rs b/src/librustc_lexer/src/unescape/tests.rs index 496527eb265..e7b1ff6479d 100644 --- a/src/librustc_lexer/src/unescape/tests.rs +++ b/src/librustc_lexer/src/unescape/tests.rs @@ -11,7 +11,6 @@ fn test_unescape_char_bad() { check(r"\", EscapeError::LoneSlash); check("\n", EscapeError::EscapeOnlyChar); - check("\r\n", EscapeError::EscapeOnlyChar); check("\t", EscapeError::EscapeOnlyChar); check("'", EscapeError::EscapeOnlyChar); check("\r", EscapeError::BareCarriageReturn); @@ -31,6 +30,7 @@ fn test_unescape_char_bad() { check(r"\v", EscapeError::InvalidEscape); check(r"\💩", EscapeError::InvalidEscape); check(r"\●", EscapeError::InvalidEscape); + check("\\\r", EscapeError::InvalidEscape); check(r"\x", EscapeError::TooShortHexEscape); check(r"\x0", EscapeError::TooShortHexEscape); @@ -116,10 +116,9 @@ fn test_unescape_str_good() { check("foo", "foo"); check("", ""); - check(" \t\n\r\n", " \t\n\n"); + check(" \t\n", " \t\n"); check("hello \\\n world", "hello world"); - check("hello \\\r\n world", "hello world"); check("thread's", "thread's") } @@ -134,7 +133,6 @@ fn test_unescape_byte_bad() { check(r"\", EscapeError::LoneSlash); check("\n", EscapeError::EscapeOnlyChar); - check("\r\n", EscapeError::EscapeOnlyChar); check("\t", EscapeError::EscapeOnlyChar); check("'", EscapeError::EscapeOnlyChar); check("\r", EscapeError::BareCarriageReturn); @@ -238,10 +236,9 @@ fn test_unescape_byte_str_good() { check("foo", b"foo"); check("", b""); - check(" \t\n\r\n", b" \t\n\n"); + check(" \t\n", b" \t\n"); check("hello \\\n world", b"hello world"); - check("hello \\\r\n world", b"hello world"); check("thread's", b"thread's") } @@ -253,7 +250,6 @@ fn test_unescape_raw_str() { assert_eq!(unescaped, expected); } - check("\r\n", &[(0..2, Ok('\n'))]); check("\r", &[(0..1, Err(EscapeError::BareCarriageReturnInRawString))]); check("\rx", &[(0..1, Err(EscapeError::BareCarriageReturnInRawString)), (1..2, Ok('x'))]); } @@ -266,7 +262,6 @@ fn test_unescape_raw_byte_str() { assert_eq!(unescaped, expected); } - check("\r\n", &[(0..2, Ok(byte_from_char('\n')))]); check("\r", &[(0..1, Err(EscapeError::BareCarriageReturnInRawString))]); check("🦀", &[(0..4, Err(EscapeError::NonAsciiCharInByteString))]); check( diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index bb2a5cab7d9..ce7681c974a 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -42,7 +42,7 @@ use syntax::source_map::Spanned; use syntax::edition::Edition; use syntax::feature_gate::{self, AttributeGate, AttributeType}; use syntax::feature_gate::{Stability, deprecated_attributes}; -use syntax_pos::{BytePos, Span, SyntaxContext}; +use syntax_pos::{BytePos, Span}; use syntax::symbol::{Symbol, kw, sym}; use syntax::errors::{Applicability, DiagnosticBuilder}; use syntax::print::pprust::expr_to_string; @@ -78,7 +78,7 @@ impl EarlyLintPass for WhileTrue { if let ast::ExprKind::While(cond, ..) = &e.node { if let ast::ExprKind::Lit(ref lit) = pierce_parens(cond).node { if let ast::LitKind::Bool(true) = lit.node { - if lit.span.ctxt() == SyntaxContext::empty() { + if !lit.span.from_expansion() { let msg = "denote infinite loops with `loop { ... }`"; let condition_span = cx.sess.source_map().def_span(e.span); cx.struct_span_lint(WHILE_TRUE, condition_span, msg) @@ -164,18 +164,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonShorthandFieldPatterns { .expect("struct pattern type is not an ADT") .variant_of_res(cx.tables.qpath_res(qpath, pat.hir_id)); for fieldpat in field_pats { - if fieldpat.node.is_shorthand { + if fieldpat.is_shorthand { continue; } - if fieldpat.span.ctxt().outer_expn_info().is_some() { + if fieldpat.span.from_expansion() { // Don't lint if this is a macro expansion: macro authors // shouldn't have to worry about this kind of style issue // (Issue #49588) continue; } - if let PatKind::Binding(_, _, ident, None) = fieldpat.node.pat.node { + if let PatKind::Binding(_, _, ident, None) = fieldpat.pat.node { if cx.tcx.find_field_index(ident, &variant) == - Some(cx.tcx.field_index(fieldpat.node.hir_id, cx.tables)) { + Some(cx.tcx.field_index(fieldpat.hir_id, cx.tables)) { let mut err = cx.struct_span_lint(NON_SHORTHAND_FIELD_PATTERNS, fieldpat.span, &format!("the `{}:` in this pattern is redundant", ident)); @@ -484,8 +484,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { fn check_variant(&mut self, cx: &LateContext<'_, '_>, v: &hir::Variant, _: &hir::Generics) { self.check_missing_docs_attrs(cx, - Some(v.node.id), - &v.node.attrs, + Some(v.id), + &v.attrs, v.span, "a variant"); } @@ -1012,7 +1012,7 @@ impl UnreachablePub { let mut applicability = Applicability::MachineApplicable; match vis.node { hir::VisibilityKind::Public if !cx.access_levels.is_reachable(id) => { - if span.ctxt().outer_expn_info().is_some() { + if span.from_expansion() { applicability = Applicability::MaybeIncorrect; } let def_span = cx.tcx.sess.source_map().def_span(span); @@ -1493,7 +1493,7 @@ impl EarlyLintPass for KeywordIdents { self.check_tokens(cx, mac_def.stream()); } fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &ast::Mac) { - self.check_tokens(cx, mac.node.tts.clone().into()); + self.check_tokens(cx, mac.tts.clone().into()); } fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: ast::Ident) { self.check_ident_token(cx, UnderMacro(false), ident); @@ -1876,16 +1876,70 @@ declare_lint_pass!(InvalidValue => [INVALID_VALUE]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &hir::Expr) { - const ZEROED_PATH: &[Symbol] = &[sym::core, sym::mem, sym::zeroed]; - const UININIT_PATH: &[Symbol] = &[sym::core, sym::mem, sym::uninitialized]; + #[derive(Debug, Copy, Clone, PartialEq)] + enum InitKind { Zeroed, Uninit }; /// Information about why a type cannot be initialized this way. /// Contains an error message and optionally a span to point at. type InitError = (String, Option<Span>); + /// Test if this constant is all-0. + fn is_zero(expr: &hir::Expr) -> bool { + use hir::ExprKind::*; + use syntax::ast::LitKind::*; + match &expr.node { + Lit(lit) => + if let Int(i, _) = lit.node { + i == 0 + } else { + false + }, + Tup(tup) => + tup.iter().all(is_zero), + _ => + false + } + } + + /// Determine if this expression is a "dangerous initialization". + fn is_dangerous_init(cx: &LateContext<'_, '_>, expr: &hir::Expr) -> Option<InitKind> { + const ZEROED_PATH: &[Symbol] = &[sym::core, sym::mem, sym::zeroed]; + const UININIT_PATH: &[Symbol] = &[sym::core, sym::mem, sym::uninitialized]; + // `transmute` is inside an anonymous module (the `extern` block?); + // `Invalid` represents the empty string and matches that. + const TRANSMUTE_PATH: &[Symbol] = + &[sym::core, sym::intrinsics, kw::Invalid, sym::transmute]; + + if let hir::ExprKind::Call(ref path_expr, ref args) = expr.node { + if let hir::ExprKind::Path(ref qpath) = path_expr.node { + let def_id = cx.tables.qpath_res(qpath, path_expr.hir_id).opt_def_id()?; + + if cx.match_def_path(def_id, ZEROED_PATH) { + return Some(InitKind::Zeroed); + } + if cx.match_def_path(def_id, UININIT_PATH) { + return Some(InitKind::Uninit); + } + if cx.match_def_path(def_id, TRANSMUTE_PATH) { + if is_zero(&args[0]) { + return Some(InitKind::Zeroed); + } + } + // FIXME: Also detect `MaybeUninit::zeroed().assume_init()` and + // `MaybeUninit::uninit().assume_init()`. + } + } + + None + } + /// Return `Some` only if we are sure this type does *not* /// allow zero initialization. - fn ty_find_init_error<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<InitError> { + fn ty_find_init_error<'tcx>( + tcx: TyCtxt<'tcx>, + ty: Ty<'tcx>, + init: InitKind, + ) -> Option<InitError> { use rustc::ty::TyKind::*; match ty.sty { // Primitive types that don't like 0 as a value. @@ -1893,8 +1947,30 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue { Adt(..) if ty.is_box() => Some((format!("`Box` must be non-null"), None)), FnPtr(..) => Some((format!("Function pointers must be non-null"), None)), Never => Some((format!("The never type (`!`) has no valid value"), None)), - // Recurse for some compound types. + // Primitive types with other constraints. + Bool if init == InitKind::Uninit => + Some((format!("Booleans must be `true` or `false`"), None)), + Char if init == InitKind::Uninit => + Some((format!("Characters must be a valid unicode codepoint"), None)), + // Recurse and checks for some compound types. Adt(adt_def, substs) if !adt_def.is_union() => { + // First check f this ADT has a layout attribute (like `NonNull` and friends). + use std::ops::Bound; + match tcx.layout_scalar_valid_range(adt_def.did) { + // We exploit here that `layout_scalar_valid_range` will never + // return `Bound::Excluded`. (And we have tests checking that we + // handle the attribute correctly.) + (Bound::Included(lo), _) if lo > 0 => + return Some((format!("{} must be non-null", ty), None)), + (Bound::Included(_), _) | (_, Bound::Included(_)) + if init == InitKind::Uninit => + return Some(( + format!("{} must be initialized inside its custom valid range", ty), + None, + )), + _ => {} + } + // Now, recurse. match adt_def.variants.len() { 0 => Some((format!("0-variant enums have no valid value"), None)), 1 => { @@ -1905,6 +1981,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue { ty_find_init_error( tcx, field.ty(tcx, substs), + init, ).map(|(mut msg, span)| if span.is_none() { // Point to this field, should be helpful for figuring // out where the source of the error is. @@ -1918,57 +1995,48 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue { }) }) } + // Multi-variant enums are tricky: if all but one variant are + // uninhabited, we might actually do layout like for a single-variant + // enum, and then even leaving them uninitialized could be okay. _ => None, // Conservative fallback for multi-variant enum. } } Tuple(..) => { // Proceed recursively, check all fields. - ty.tuple_fields().find_map(|field| ty_find_init_error(tcx, field)) + ty.tuple_fields().find_map(|field| ty_find_init_error(tcx, field, init)) } - // FIXME: Would be nice to also warn for `NonNull`/`NonZero*`. - // FIXME: *Only for `mem::uninitialized`*, we could also warn for `bool`, - // `char`, and any multivariant enum. // Conservative fallback. _ => None, } } - if let hir::ExprKind::Call(ref path_expr, ref _args) = expr.node { - if let hir::ExprKind::Path(ref qpath) = path_expr.node { - if let Some(def_id) = cx.tables.qpath_res(qpath, path_expr.hir_id).opt_def_id() { - if cx.match_def_path(def_id, &ZEROED_PATH) || - cx.match_def_path(def_id, &UININIT_PATH) - { - // This conjures an instance of a type out of nothing, - // using zeroed or uninitialized memory. - // We are extremely conservative with what we warn about. - let conjured_ty = cx.tables.expr_ty(expr); - if let Some((msg, span)) = ty_find_init_error(cx.tcx, conjured_ty) { - let mut err = cx.struct_span_lint( - INVALID_VALUE, - expr.span, - &format!( - "the type `{}` does not permit {}", - conjured_ty, - if cx.match_def_path(def_id, &ZEROED_PATH) { - "zero-initialization" - } else { - "being left uninitialized" - } - ), - ); - err.span_label(expr.span, - "this code causes undefined behavior when executed"); - err.span_label(expr.span, "help: use `MaybeUninit<T>` instead"); - if let Some(span) = span { - err.span_note(span, &msg); - } else { - err.note(&msg); - } - err.emit(); - } - } + if let Some(init) = is_dangerous_init(cx, expr) { + // This conjures an instance of a type out of nothing, + // using zeroed or uninitialized memory. + // We are extremely conservative with what we warn about. + let conjured_ty = cx.tables.expr_ty(expr); + if let Some((msg, span)) = ty_find_init_error(cx.tcx, conjured_ty, init) { + let mut err = cx.struct_span_lint( + INVALID_VALUE, + expr.span, + &format!( + "the type `{}` does not permit {}", + conjured_ty, + match init { + InitKind::Zeroed => "zero-initialization", + InitKind::Uninit => "being left uninitialized", + }, + ), + ); + err.span_label(expr.span, + "this code causes undefined behavior when executed"); + err.span_label(expr.span, "help: use `MaybeUninit<T>` instead"); + if let Some(span) = span { + err.span_note(span, &msg); + } else { + err.note(&msg); } + err.emit(); } } } diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 3a540fdf4b9..27833161ef2 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -3,7 +3,7 @@ //! This currently only contains the definitions and implementations //! of most of the lints that `rustc` supports directly, it does not //! contain the infrastructure for defining/registering lints. That is -//! available in `rustc::lint` and `rustc_plugin` respectively. +//! available in `rustc::lint` and `rustc_driver::plugin` respectively. //! //! ## Note //! @@ -24,6 +24,7 @@ extern crate rustc; mod error_codes; mod nonstandard_style; +mod redundant_semicolon; pub mod builtin; mod types; mod unused; @@ -55,6 +56,7 @@ use session::Session; use lint::LintId; use lint::FutureIncompatibleInfo; +use redundant_semicolon::*; use nonstandard_style::*; use builtin::*; use types::*; @@ -98,6 +100,7 @@ macro_rules! early_lint_passes { WhileTrue: WhileTrue, NonAsciiIdents: NonAsciiIdents, IncompleteFeatures: IncompleteFeatures, + RedundantSemicolon: RedundantSemicolon, ]); ) } diff --git a/src/librustc_lint/nonstandard_style.rs b/src/librustc_lint/nonstandard_style.rs index 8f7fe6680cb..acd17f76632 100644 --- a/src/librustc_lint/nonstandard_style.rs +++ b/src/librustc_lint/nonstandard_style.rs @@ -147,7 +147,7 @@ impl EarlyLintPass for NonCamelCaseTypes { } fn check_variant(&mut self, cx: &EarlyContext<'_>, v: &ast::Variant, _: &ast::Generics) { - self.check_case(cx, "variant", &v.node.ident); + self.check_case(cx, "variant", &v.ident); } fn check_generic_param(&mut self, cx: &EarlyContext<'_>, param: &ast::GenericParam) { diff --git a/src/librustc_lint/redundant_semicolon.rs b/src/librustc_lint/redundant_semicolon.rs new file mode 100644 index 00000000000..7c9df3578b5 --- /dev/null +++ b/src/librustc_lint/redundant_semicolon.rs @@ -0,0 +1,52 @@ +use crate::lint::{EarlyLintPass, LintPass, EarlyContext, LintArray, LintContext}; +use syntax::ast::{Stmt, StmtKind, ExprKind}; +use syntax::errors::Applicability; + +declare_lint! { + pub REDUNDANT_SEMICOLON, + Warn, + "detects unnecessary trailing semicolons" +} + +declare_lint_pass!(RedundantSemicolon => [REDUNDANT_SEMICOLON]); + +impl EarlyLintPass for RedundantSemicolon { + fn check_stmt(&mut self, cx: &EarlyContext<'_>, stmt: &Stmt) { + if let StmtKind::Semi(expr) = &stmt.node { + if let ExprKind::Tup(ref v) = &expr.node { + if v.is_empty() { + // Strings of excess semicolons are encoded as empty tuple expressions + // during the parsing stage, so we check for empty tuple expressions + // which span only semicolons + if let Ok(source_str) = cx.sess().source_map().span_to_snippet(stmt.span) { + if source_str.chars().all(|c| c == ';') { + let multiple = (stmt.span.hi() - stmt.span.lo()).0 > 1; + let msg = if multiple { + "unnecessary trailing semicolons" + } else { + "unnecessary trailing semicolon" + }; + let mut err = cx.struct_span_lint( + REDUNDANT_SEMICOLON, + stmt.span, + &msg + ); + let suggest_msg = if multiple { + "remove these semicolons" + } else { + "remove this semicolon" + }; + err.span_suggestion( + stmt.span, + &suggest_msg, + String::new(), + Applicability::MaybeIncorrect + ); + err.emit(); + } + } + } + } + } + } +} diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index e86230437f2..217e10ab24f 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -976,7 +976,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences { let bytes = variant_layout.size.bytes().saturating_sub(discr_size); debug!("- variant `{}` is {} bytes large", - variant.node.ident, + variant.ident, bytes); bytes }) diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 6a3dfdbe316..90e46771396 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -517,9 +517,8 @@ impl EarlyLintPass for UnusedParens { // trigger in situations that macro authors shouldn't have to care about, e.g., // when a parenthesized token tree matched in one macro expansion is matched as // an expression in another and used as a fn/method argument (Issue #47775) - if e.span.ctxt().outer_expn_info() - .map_or(false, |info| info.call_site.ctxt().outer_expn_info().is_some()) { - return; + if e.span.ctxt().outer_expn_data().call_site.from_expansion() { + return; } let msg = format!("{} argument", call_kind); for arg in args_to_check { diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs index 16cdbb7dd4d..40ddd651642 100644 --- a/src/librustc_llvm/build.rs +++ b/src/librustc_llvm/build.rs @@ -151,6 +151,10 @@ fn main() { cfg.define("LLVM_RUSTLLVM", None); } + if env::var_os("LLVM_NDEBUG").is_some() { + cfg.define("NDEBUG", None); + } + build_helper::rerun_if_changed_anything_in_dir(Path::new("../rustllvm")); cfg.file("../rustllvm/PassWrapper.cpp") .file("../rustllvm/RustWrapper.cpp") @@ -250,8 +254,11 @@ fn main() { let llvm_use_libcxx = env::var_os("LLVM_USE_LIBCXX"); let stdcppname = if target.contains("openbsd") { - // llvm-config on OpenBSD doesn't mention stdlib=libc++ - "c++" + if target.contains("sparc64") { + "estdc++" + } else { + "c++" + } } else if target.contains("freebsd") { "c++" } else if target.contains("darwin") { diff --git a/src/librustc_macros/src/lib.rs b/src/librustc_macros/src/lib.rs index 85e2247ebd7..3d3a020ef0c 100644 --- a/src/librustc_macros/src/lib.rs +++ b/src/librustc_macros/src/lib.rs @@ -1,5 +1,5 @@ #![feature(proc_macro_hygiene)] -#![cfg_attr(not(bootstrap), allow(rustc::default_hash_types))] +#![allow(rustc::default_hash_types)] #![recursion_limit="128"] diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index d5f1e715186..af41b6a4c85 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -2,8 +2,7 @@ use crate::cstore::{self, CStore, CrateSource, MetadataBlob}; use crate::locator::{self, CratePaths}; -use crate::decoder::proc_macro_def_path_table; -use crate::schema::CrateRoot; +use crate::schema::{CrateRoot}; use rustc_data_structures::sync::{Lrc, RwLock, Lock}; use rustc::hir::def_id::CrateNum; @@ -26,11 +25,11 @@ use std::{cmp, fs}; use syntax::ast; use syntax::attr; use syntax::ext::allocator::{global_allocator_spans, AllocatorKind}; -use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind}; use syntax::symbol::{Symbol, sym}; use syntax::{span_err, span_fatal}; use syntax_pos::{Span, DUMMY_SP}; use log::{debug, info, log_enabled}; +use proc_macro::bridge::client::ProcMacro; pub struct Library { pub dylib: Option<(PathBuf, PathKind)>, @@ -230,24 +229,13 @@ impl<'a> CrateLoader<'a> { let dependencies: Vec<CrateNum> = cnum_map.iter().cloned().collect(); - let proc_macros = crate_root.proc_macro_decls_static.map(|_| { + let raw_proc_macros = crate_root.proc_macro_data.map(|_| { if self.sess.opts.debugging_opts.dual_proc_macros { - let host_lib = host_lib.unwrap(); - self.load_derive_macros( - &host_lib.metadata.get_root(), - host_lib.dylib.map(|p| p.0), - span - ) + let host_lib = host_lib.as_ref().unwrap(); + self.dlsym_proc_macros(host_lib.dylib.as_ref().map(|p| p.0.clone()), + &host_lib.metadata.get_root(), span) } else { - self.load_derive_macros(&crate_root, dylib.clone().map(|p| p.0), span) - } - }); - - let def_path_table = record_time(&self.sess.perf_stats.decode_def_path_tables_time, || { - if let Some(proc_macros) = &proc_macros { - proc_macro_def_path_table(&crate_root, proc_macros) - } else { - crate_root.def_path_table.decode((&metadata, self.sess)) + self.dlsym_proc_macros(dylib.clone().map(|p| p.0), &crate_root, span) } }); @@ -260,13 +248,16 @@ impl<'a> CrateLoader<'a> { .map(|trait_impls| (trait_impls.trait_id, trait_impls.impls)) .collect(); + let def_path_table = record_time(&self.sess.perf_stats.decode_def_path_tables_time, || { + crate_root.def_path_table.decode((&metadata, self.sess)) + }); + let cmeta = cstore::CrateMetadata { name: crate_root.name, imported_name: ident, extern_crate: Lock::new(None), def_path_table: Lrc::new(def_path_table), trait_impls, - proc_macros, root: crate_root, blob: metadata, cnum_map, @@ -280,7 +271,10 @@ impl<'a> CrateLoader<'a> { rlib, rmeta, }, - private_dep + private_dep, + span, + host_lib, + raw_proc_macros }; let cmeta = Lrc::new(cmeta); @@ -389,7 +383,7 @@ impl<'a> CrateLoader<'a> { match result { (LoadResult::Previous(cnum), None) => { let data = self.cstore.get_crate_data(cnum); - if data.root.proc_macro_decls_static.is_some() { + if data.root.proc_macro_data.is_some() { dep_kind = DepKind::UnexportedMacrosOnly; } data.dep_kind.with_lock(|data_dep_kind| { @@ -482,7 +476,7 @@ impl<'a> CrateLoader<'a> { dep_kind: DepKind) -> cstore::CrateNumMap { debug!("resolving deps of external crate"); - if crate_root.proc_macro_decls_static.is_some() { + if crate_root.proc_macro_data.is_some() { return cstore::CrateNumMap::new(); } @@ -574,19 +568,13 @@ impl<'a> CrateLoader<'a> { } } - /// Loads custom derive macros. - /// - /// Note that this is intentionally similar to how we load plugins today, - /// but also intentionally separate. Plugins are likely always going to be - /// implemented as dynamic libraries, but we have a possible future where - /// custom derive (and other macro-1.1 style features) are implemented via - /// executables and custom IPC. - fn load_derive_macros(&mut self, root: &CrateRoot<'_>, dylib: Option<PathBuf>, span: Span) - -> Vec<(ast::Name, Lrc<SyntaxExtension>)> { - use std::{env, mem}; + fn dlsym_proc_macros(&self, + dylib: Option<PathBuf>, + root: &CrateRoot<'_>, + span: Span + ) -> &'static [ProcMacro] { + use std::env; use crate::dynamic_lib::DynamicLibrary; - use proc_macro::bridge::client::ProcMacro; - use syntax::ext::proc_macro::{BangProcMacro, AttrProcMacro, ProcMacroDerive}; let path = match dylib { Some(dylib) => dylib, @@ -608,38 +596,11 @@ impl<'a> CrateLoader<'a> { *(sym as *const &[ProcMacro]) }; - let extensions = decls.iter().map(|&decl| { - let (name, kind, helper_attrs) = match decl { - ProcMacro::CustomDerive { trait_name, attributes, client } => { - let helper_attrs = - attributes.iter().cloned().map(Symbol::intern).collect::<Vec<_>>(); - ( - trait_name, - SyntaxExtensionKind::Derive(Box::new(ProcMacroDerive { - client, attrs: helper_attrs.clone() - })), - helper_attrs, - ) - } - ProcMacro::Attr { name, client } => ( - name, SyntaxExtensionKind::Attr(Box::new(AttrProcMacro { client })), Vec::new() - ), - ProcMacro::Bang { name, client } => ( - name, SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client })), Vec::new() - ) - }; - - (Symbol::intern(name), Lrc::new(SyntaxExtension { - helper_attrs, - ..SyntaxExtension::default(kind, root.edition) - })) - }).collect(); - // Intentionally leak the dynamic library. We can't ever unload it // since the library can make things that will live arbitrarily long. - mem::forget(lib); + std::mem::forget(lib); - extensions + decls } /// Look for a plugin registrar. Returns library path, crate diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index 5d8fabc7e69..efc77699313 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -28,6 +28,9 @@ pub use crate::cstore_impl::{provide, provide_extern}; pub type CrateNumMap = IndexVec<CrateNum, CrateNum>; pub use rustc_data_structures::sync::MetadataRef; +use crate::creader::Library; +use syntax_pos::Span; +use proc_macro::bridge::client::ProcMacro; pub struct MetadataBlob(pub MetadataRef); @@ -65,28 +68,36 @@ pub struct CrateMetadata { pub alloc_decoding_state: AllocDecodingState, // NOTE(eddyb) we pass `'static` to a `'tcx` parameter because this - // lifetime is only used behind `Lazy` / `LazySeq`, and therefore - // acts like an universal (`for<'tcx>`), that is paired up with - // whichever `TyCtxt` is being used to decode those values. + // lifetime is only used behind `Lazy`, and therefore acts like an + // universal (`for<'tcx>`), that is paired up with whichever `TyCtxt` + // is being used to decode those values. pub root: schema::CrateRoot<'static>, - /// For each public item in this crate, we encode a key. When the + /// For each definition in this crate, we encode a key. When the /// crate is loaded, we read all the keys and put them in this /// hashmap, which gives the reverse mapping. This allows us to /// quickly retrace a `DefPath`, which is needed for incremental /// compilation support. pub def_path_table: Lrc<DefPathTable>, - pub trait_impls: FxHashMap<(u32, DefIndex), schema::LazySeq<DefIndex>>, + pub trait_impls: FxHashMap<(u32, DefIndex), schema::Lazy<[DefIndex]>>, pub dep_kind: Lock<DepKind>, pub source: CrateSource, - pub proc_macros: Option<Vec<(ast::Name, Lrc<SyntaxExtension>)>>, - /// Whether or not this crate should be consider a private dependency /// for purposes of the 'exported_private_dependencies' lint - pub private_dep: bool + pub private_dep: bool, + + pub host_lib: Option<Library>, + pub span: Span, + + pub raw_proc_macros: Option<&'static [ProcMacro]>, +} + +pub struct FullProcMacro { + pub name: ast::Name, + pub ext: Lrc<SyntaxExtension> } pub struct CStore { diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index ee1175e798d..a66da32fa4d 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -35,7 +35,7 @@ use syntax::ext::proc_macro::BangProcMacro; use syntax::parse::source_file_to_stream; use syntax::parse::parser::emit_unclosed_delims; use syntax::symbol::{Symbol, sym}; -use syntax_pos::{Span, NO_EXPANSION, FileName}; +use syntax_pos::{Span, FileName}; use rustc_data_structures::bit_set::BitSet; macro_rules! provide { @@ -426,8 +426,8 @@ impl cstore::CStore { pub fn load_macro_untracked(&self, id: DefId, sess: &Session) -> LoadedMacro { let data = self.get_crate_data(id.krate); - if let Some(ref proc_macros) = data.proc_macros { - return LoadedMacro::ProcMacro(proc_macros[id.index.to_proc_macro_index()].1.clone()); + if data.is_proc_macro_crate() { + return LoadedMacro::ProcMacro(data.get_proc_macro(id.index, sess).ext); } else if data.name == sym::proc_macro && data.item_name(id.index) == sym::quote { let client = proc_macro::bridge::client::Client::expand1(proc_macro::quote); let kind = SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client })); @@ -439,11 +439,12 @@ impl cstore::CStore { } let def = data.get_macro(id.index); - let macro_full_name = data.def_path(id.index).to_string_friendly(|_| data.imported_name); + let macro_full_name = data.def_path(id.index) + .to_string_friendly(|_| data.imported_name); let source_name = FileName::Macros(macro_full_name); let source_file = sess.parse_sess.source_map().new_source_file(source_name, def.body); - let local_span = Span::new(source_file.start_pos, source_file.end_pos, NO_EXPANSION); + let local_span = Span::with_root_ctxt(source_file.start_pos, source_file.end_pos); let (body, mut errors) = source_file_to_stream(&sess.parse_sess, source_file, None); emit_unclosed_delims(&mut errors, &sess.diagnostic()); diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 935187dd066..da96728d2de 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -1,16 +1,15 @@ // Decoding metadata from a single crate's metadata -use crate::cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary, ForeignModule}; +use crate::cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary, ForeignModule, FullProcMacro}; use crate::schema::*; use rustc_data_structures::sync::{Lrc, ReadGuard}; -use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash, Definitions}; +use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash}; use rustc::hir; use rustc::middle::cstore::LinkagePreference; use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel}; use rustc::hir::def::{self, Res, DefKind, CtorOf, CtorKind}; use rustc::hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE}; -use rustc::hir::map::definitions::DefPathTable; use rustc_data_structures::fingerprint::Fingerprint; use rustc::middle::lang_items; use rustc::mir::{self, interpret}; @@ -30,10 +29,11 @@ use syntax::attr; use syntax::ast::{self, Ident}; use syntax::source_map; use syntax::symbol::{Symbol, sym}; -use syntax::ext::base::{MacroKind, SyntaxExtension}; -use syntax::ext::hygiene::ExpnId; -use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP, NO_EXPANSION}; +use syntax::ext::base::{MacroKind, SyntaxExtensionKind, SyntaxExtension}; +use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP, symbol::{InternedString}}; use log::debug; +use proc_macro::bridge::client::ProcMacro; +use syntax::ext::proc_macro::{AttrProcMacro, ProcMacroDerive, BangProcMacro}; pub struct DecodeContext<'a, 'tcx> { opaque: opaque::Decoder<'a>, @@ -134,14 +134,14 @@ impl<'a, 'tcx, T: Decodable> Lazy<T> { } } -impl<'a: 'x, 'tcx: 'x, 'x, T: Decodable> LazySeq<T> { +impl<'a: 'x, 'tcx: 'x, 'x, T: Decodable> Lazy<[T]> { pub fn decode<M: Metadata<'a, 'tcx>>( self, meta: M, - ) -> impl Iterator<Item = T> + Captures<'a> + Captures<'tcx> + 'x { + ) -> impl ExactSizeIterator<Item = T> + Captures<'a> + Captures<'tcx> + 'x { let mut dcx = meta.decoder(self.position); dcx.lazy_state = LazyState::NodeStart(self.position); - (0..self.len).map(move |_| T::decode(&mut dcx).unwrap()) + (0..self.meta).map(move |_| T::decode(&mut dcx).unwrap()) } } @@ -154,10 +154,14 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> { self.cdata.expect("missing CrateMetadata in DecodeContext") } - fn read_lazy_distance(&mut self, min_size: usize) -> Result<usize, <Self as Decoder>::Error> { + fn read_lazy_with_meta<T: ?Sized + LazyMeta>( + &mut self, + meta: T::Meta, + ) -> Result<Lazy<T>, <Self as Decoder>::Error> { + let min_size = T::min_size(meta); let distance = self.read_usize()?; let position = match self.lazy_state { - LazyState::NoNode => bug!("read_lazy_distance: outside of a metadata node"), + LazyState::NoNode => bug!("read_lazy_with_meta: outside of a metadata node"), LazyState::NodeStart(start) => { assert!(distance + min_size <= start); start - distance - min_size @@ -165,7 +169,7 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> { LazyState::Previous(last_min_end) => last_min_end + distance, }; self.lazy_state = LazyState::Previous(position + min_size); - Ok(position) + Ok(Lazy::from_position_and_meta(position, meta)) } } @@ -230,19 +234,18 @@ impl<'a, 'tcx> TyDecoder<'tcx> for DecodeContext<'a, 'tcx> { impl<'a, 'tcx, T> SpecializedDecoder<Lazy<T>> for DecodeContext<'a, 'tcx> { fn specialized_decode(&mut self) -> Result<Lazy<T>, Self::Error> { - Ok(Lazy::with_position(self.read_lazy_distance(Lazy::<T>::min_size())?)) + self.read_lazy_with_meta(()) } } -impl<'a, 'tcx, T> SpecializedDecoder<LazySeq<T>> for DecodeContext<'a, 'tcx> { - fn specialized_decode(&mut self) -> Result<LazySeq<T>, Self::Error> { +impl<'a, 'tcx, T> SpecializedDecoder<Lazy<[T]>> for DecodeContext<'a, 'tcx> { + fn specialized_decode(&mut self) -> Result<Lazy<[T]>, Self::Error> { let len = self.read_usize()?; - let position = if len == 0 { - 0 + if len == 0 { + Ok(Lazy::empty()) } else { - self.read_lazy_distance(LazySeq::<T>::min_size(len))? - }; - Ok(LazySeq::with_position_and_length(position, len)) + self.read_lazy_with_meta(len) + } } } @@ -344,7 +347,15 @@ impl<'a, 'tcx> SpecializedDecoder<Span> for DecodeContext<'a, 'tcx> { let hi = (hi + source_file.translated_source_file.start_pos) - source_file.original_start_pos; - Ok(Span::new(lo, hi, NO_EXPANSION)) + Ok(Span::with_root_ctxt(lo, hi)) + } +} + +impl SpecializedDecoder<Ident> for DecodeContext<'_, '_> { + fn specialized_decode(&mut self) -> Result<Ident, Self::Error> { + // FIXME(jseyfried): intercrate hygiene + + Ok(Ident::with_dummy_span(Symbol::decode(self)?)) } } @@ -370,7 +381,7 @@ impl<'tcx> MetadataBlob { } pub fn get_rustc_version(&self) -> String { - Lazy::with_position(METADATA_HEADER.len() + 4).decode(self) + Lazy::<String>::from_position(METADATA_HEADER.len() + 4).decode(self) } pub fn get_root(&self) -> CrateRoot<'tcx> { @@ -379,7 +390,7 @@ impl<'tcx> MetadataBlob { let pos = (((slice[offset + 0] as u32) << 24) | ((slice[offset + 1] as u32) << 16) | ((slice[offset + 2] as u32) << 8) | ((slice[offset + 3] as u32) << 0)) as usize; - Lazy::with_position(pos).decode(self) + Lazy::<CrateRoot<'tcx>>::from_position(pos).decode(self) } pub fn list_crate_metadata(&self, @@ -434,46 +445,16 @@ impl<'tcx> EntryKind<'tcx> { } } -/// Creates the "fake" DefPathTable for a given proc macro crate. -/// -/// The DefPathTable is as follows: -/// -/// CRATE_ROOT (DefIndex 0:0) -/// |- GlobalMetaDataKind data (DefIndex 1:0 .. DefIndex 1:N) -/// |- proc macro #0 (DefIndex 1:N) -/// |- proc macro #1 (DefIndex 1:N+1) -/// \- ... -crate fn proc_macro_def_path_table(crate_root: &CrateRoot<'_>, - proc_macros: &[(ast::Name, Lrc<SyntaxExtension>)]) - -> DefPathTable -{ - let mut definitions = Definitions::default(); - - let name = crate_root.name.as_str(); - let disambiguator = crate_root.disambiguator; - debug!("creating proc macro def path table for {:?}/{:?}", name, disambiguator); - let crate_root = definitions.create_root_def(&name, disambiguator); - for (index, (name, _)) in proc_macros.iter().enumerate() { - let def_index = definitions.create_def_with_parent( - crate_root, - ast::DUMMY_NODE_ID, - DefPathData::MacroNs(name.as_interned_str()), - ExpnId::root(), - DUMMY_SP); - debug!("definition for {:?} is {:?}", name, def_index); - assert_eq!(def_index, DefIndex::from_proc_macro_index(index)); - } - - definitions.def_path_table().clone() -} - impl<'a, 'tcx> CrateMetadata { + pub fn is_proc_macro_crate(&self) -> bool { + self.root.proc_macro_decls_static.is_some() + } fn is_proc_macro(&self, id: DefIndex) -> bool { - self.proc_macros.is_some() && id != CRATE_DEF_INDEX + self.is_proc_macro_crate() && + self.root.proc_macro_data.unwrap().decode(self).find(|x| *x == id).is_some() } fn maybe_entry(&self, item_id: DefIndex) -> Option<Lazy<Entry<'tcx>>> { - assert!(!self.is_proc_macro(item_id)); self.root.entries_index.lookup(self.blob.raw_bytes(), item_id) } @@ -496,13 +477,24 @@ impl<'a, 'tcx> CrateMetadata { } } + fn raw_proc_macro(&self, id: DefIndex) -> &ProcMacro { + // DefIndex's in root.proc_macro_data have a one-to-one correspondence + // with items in 'raw_proc_macros' + let pos = self.root.proc_macro_data.unwrap().decode(self).position(|i| i == id).unwrap(); + &self.raw_proc_macros.unwrap()[pos] + } + pub fn item_name(&self, item_index: DefIndex) -> Symbol { - self.def_key(item_index) - .disambiguated_data - .data - .get_opt_name() - .expect("no name in item_name") - .as_symbol() + if !self.is_proc_macro(item_index) { + self.def_key(item_index) + .disambiguated_data + .data + .get_opt_name() + .expect("no name in item_name") + .as_symbol() + } else { + Symbol::intern(self.raw_proc_macro(item_index).name()) + } } pub fn def_kind(&self, index: DefIndex) -> Option<DefKind> { @@ -510,15 +502,64 @@ impl<'a, 'tcx> CrateMetadata { self.entry(index).kind.def_kind() } else { Some(DefKind::Macro( - self.proc_macros.as_ref().unwrap()[index.to_proc_macro_index()].1.macro_kind() + macro_kind(self.raw_proc_macro(index)) )) } } pub fn get_span(&self, index: DefIndex, sess: &Session) -> Span { - match self.is_proc_macro(index) { - true => DUMMY_SP, - false => self.entry(index).span.decode((self, sess)), + self.entry(index).span.decode((self, sess)) + } + + + pub fn get_proc_macro(&self, id: DefIndex, sess: &Session) -> FullProcMacro { + if sess.opts.debugging_opts.dual_proc_macros { + let host_lib = self.host_lib.as_ref().unwrap(); + self.load_proc_macro( + &host_lib.metadata.get_root(), + id, + sess + ) + } else { + self.load_proc_macro(&self.root, id, sess) + } + } + + fn load_proc_macro(&self, root: &CrateRoot<'_>, + id: DefIndex, + sess: &Session) + -> FullProcMacro { + + let raw_macro = self.raw_proc_macro(id); + let (name, kind, helper_attrs) = match *raw_macro { + ProcMacro::CustomDerive { trait_name, attributes, client } => { + let helper_attrs = + attributes.iter().cloned().map(Symbol::intern).collect::<Vec<_>>(); + ( + trait_name, + SyntaxExtensionKind::Derive(Box::new(ProcMacroDerive { + client, attrs: helper_attrs.clone() + })), + helper_attrs, + ) + } + ProcMacro::Attr { name, client } => ( + name, SyntaxExtensionKind::Attr(Box::new(AttrProcMacro { client })), Vec::new() + ), + ProcMacro::Bang { name, client } => ( + name, SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client })), Vec::new() + ) + }; + + let span = self.get_span(id, sess); + + FullProcMacro { + name: Symbol::intern(name), + ext: Lrc::new(SyntaxExtension { + span, + helper_attrs, + ..SyntaxExtension::default(kind, root.edition) + }) } } @@ -569,7 +610,7 @@ impl<'a, 'tcx> CrateMetadata { ty::VariantDef::new( tcx, - Ident::with_empty_ctxt(self.item_name(index)), + Ident::with_dummy_span(self.item_name(index)), variant_did, ctor_did, data.discr, @@ -577,7 +618,7 @@ impl<'a, 'tcx> CrateMetadata { let f = self.entry(index); ty::FieldDef { did: self.local_def_id(index), - ident: Ident::with_empty_ctxt(self.item_name(index)), + ident: Ident::with_dummy_span(self.item_name(index)), vis: f.visibility.decode(self) } }).collect(), @@ -715,7 +756,7 @@ impl<'a, 'tcx> CrateMetadata { /// Iterates over the language items in the given crate. pub fn get_lang_items(&self, tcx: TyCtxt<'tcx>) -> &'tcx [(DefId, usize)] { - if self.proc_macros.is_some() { + if self.is_proc_macro_crate() { // Proc macro crates do not export any lang-items to the target. &[] } else { @@ -730,18 +771,18 @@ impl<'a, 'tcx> CrateMetadata { pub fn each_child_of_item<F>(&self, id: DefIndex, mut callback: F, sess: &Session) where F: FnMut(def::Export<hir::HirId>) { - if let Some(ref proc_macros) = self.proc_macros { + if let Some(proc_macros_ids) = self.root.proc_macro_data.map(|d| d.decode(self)) { /* If we are loading as a proc macro, we want to return the view of this crate - * as a proc macro crate, not as a Rust crate. See `proc_macro_def_path_table` - * for the DefPathTable we are corresponding to. + * as a proc macro crate. */ if id == CRATE_DEF_INDEX { - for (id, &(name, ref ext)) in proc_macros.iter().enumerate() { + for def_index in proc_macros_ids { + let raw_macro = self.raw_proc_macro(def_index); let res = Res::Def( - DefKind::Macro(ext.macro_kind()), - self.local_def_id(DefIndex::from_proc_macro_index(id)), + DefKind::Macro(macro_kind(raw_macro)), + self.local_def_id(def_index), ); - let ident = Ident::with_empty_ctxt(name); + let ident = Ident::from_str(raw_macro.name()); callback(def::Export { ident: ident, res: res, @@ -783,7 +824,7 @@ impl<'a, 'tcx> CrateMetadata { if let Some(kind) = self.def_kind(child_index) { callback(def::Export { res: Res::Def(kind, self.local_def_id(child_index)), - ident: Ident::with_empty_ctxt(self.item_name(child_index)), + ident: Ident::with_dummy_span(self.item_name(child_index)), vis: self.get_visibility(child_index), span: self.entry(child_index).span.decode((self, sess)), }); @@ -952,11 +993,8 @@ impl<'a, 'tcx> CrateMetadata { } } - pub fn get_item_attrs(&self, node_id: DefIndex, sess: &Session) -> Lrc<[ast::Attribute]> { - if self.is_proc_macro(node_id) { - return Lrc::new([]); - } + pub fn get_item_attrs(&self, node_id: DefIndex, sess: &Session) -> Lrc<[ast::Attribute]> { // The attributes for a tuple struct/variant are attached to the definition, not the ctor; // we assume that someone passing in a tuple struct ctor is actually wanting to // look at the definition @@ -1014,7 +1052,7 @@ impl<'a, 'tcx> CrateMetadata { tcx: TyCtxt<'tcx>, filter: Option<DefId>, ) -> &'tcx [DefId] { - if self.proc_macros.is_some() { + if self.is_proc_macro_crate() { // proc-macro crates export no trait impls. return &[] } @@ -1058,7 +1096,7 @@ impl<'a, 'tcx> CrateMetadata { pub fn get_native_libraries(&self, sess: &Session) -> Vec<NativeLibrary> { - if self.proc_macros.is_some() { + if self.is_proc_macro_crate() { // Proc macro crates do not have any *target* native libraries. vec![] } else { @@ -1067,7 +1105,7 @@ impl<'a, 'tcx> CrateMetadata { } pub fn get_foreign_modules(&self, tcx: TyCtxt<'tcx>) -> &'tcx [ForeignModule] { - if self.proc_macros.is_some() { + if self.is_proc_macro_crate() { // Proc macro crates do not have any *target* foreign modules. &[] } else { @@ -1090,7 +1128,7 @@ impl<'a, 'tcx> CrateMetadata { } pub fn get_missing_lang_items(&self, tcx: TyCtxt<'tcx>) -> &'tcx [lang_items::LangItem] { - if self.proc_macros.is_some() { + if self.is_proc_macro_crate() { // Proc macro crates do not depend on any target weak lang-items. &[] } else { @@ -1105,7 +1143,7 @@ impl<'a, 'tcx> CrateMetadata { EntryKind::Fn(data) | EntryKind::ForeignFn(data) => data.decode(self).arg_names, EntryKind::Method(data) => data.decode(self).fn_data.arg_names, - _ => LazySeq::empty(), + _ => Lazy::empty(), }; arg_names.decode(self).collect() } @@ -1114,7 +1152,7 @@ impl<'a, 'tcx> CrateMetadata { &self, tcx: TyCtxt<'tcx>, ) -> Vec<(ExportedSymbol<'tcx>, SymbolExportLevel)> { - if self.proc_macros.is_some() { + if self.is_proc_macro_crate() { // If this crate is a custom derive crate, then we're not even going to // link those in so we skip those crates. vec![] @@ -1183,13 +1221,18 @@ impl<'a, 'tcx> CrateMetadata { #[inline] pub fn def_key(&self, index: DefIndex) -> DefKey { - self.def_path_table.def_key(index) + 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 } // Returns the path leading to the thing with this `id`. pub fn def_path(&self, id: DefIndex) -> DefPath { debug!("def_path(cnum={:?}, id={:?})", self.cnum, id); - DefPath::make(self.cnum, id, |parent| self.def_path_table.def_key(parent)) + DefPath::make(self.cnum, id, |parent| self.def_key(parent)) } #[inline] @@ -1302,3 +1345,13 @@ impl<'a, 'tcx> CrateMetadata { self.source_map_import_info.borrow() } } + +// Cannot be implemented on 'ProcMacro', as libproc_macro +// does not depend on libsyntax +fn macro_kind(raw: &ProcMacro) -> MacroKind { + match raw { + ProcMacro::CustomDerive { .. } => MacroKind::Derive, + ProcMacro::Attr { .. } => MacroKind::Attr, + ProcMacro::Bang { .. } => MacroKind::Bang + } +} diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index d73a4966bca..df3320c64a9 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -30,8 +30,9 @@ use rustc_data_structures::sync::Lrc; use std::u32; use syntax::ast; use syntax::attr; +use syntax::ext::proc_macro::is_proc_macro_attr; use syntax::source_map::Spanned; -use syntax::symbol::{kw, sym}; +use syntax::symbol::{kw, sym, Ident}; use syntax_pos::{self, FileName, SourceFile, Span}; use log::{debug, trace}; @@ -97,17 +98,17 @@ impl<'tcx> Encoder for EncodeContext<'tcx> { impl<'tcx, T> SpecializedEncoder<Lazy<T>> for EncodeContext<'tcx> { fn specialized_encode(&mut self, lazy: &Lazy<T>) -> Result<(), Self::Error> { - self.emit_lazy_distance(lazy.position, Lazy::<T>::min_size()) + self.emit_lazy_distance(*lazy) } } -impl<'tcx, T> SpecializedEncoder<LazySeq<T>> for EncodeContext<'tcx> { - fn specialized_encode(&mut self, seq: &LazySeq<T>) -> Result<(), Self::Error> { - self.emit_usize(seq.len)?; - if seq.len == 0 { +impl<'tcx, T> SpecializedEncoder<Lazy<[T]>> for EncodeContext<'tcx> { + fn specialized_encode(&mut self, lazy: &Lazy<[T]>) -> Result<(), Self::Error> { + self.emit_usize(lazy.meta)?; + if lazy.meta == 0 { return Ok(()); } - self.emit_lazy_distance(seq.position, LazySeq::<T>::min_size(seq.len)) + self.emit_lazy_distance(*lazy) } } @@ -173,6 +174,13 @@ impl<'tcx> SpecializedEncoder<Span> for EncodeContext<'tcx> { } } +impl SpecializedEncoder<Ident> for EncodeContext<'tcx> { + fn specialized_encode(&mut self, ident: &Ident) -> Result<(), Self::Error> { + // FIXME(jseyfried): intercrate hygiene + ident.name.encode(self) + } +} + impl<'tcx> SpecializedEncoder<LocalDefId> for EncodeContext<'tcx> { #[inline] fn specialized_encode(&mut self, def_id: &LocalDefId) -> Result<(), Self::Error> { @@ -231,21 +239,38 @@ impl<'tcx> TyEncoder for EncodeContext<'tcx> { } } -impl<'tcx> EncodeContext<'tcx> { - fn emit_node<F: FnOnce(&mut Self, usize) -> R, R>(&mut self, f: F) -> R { - assert_eq!(self.lazy_state, LazyState::NoNode); - let pos = self.position(); - self.lazy_state = LazyState::NodeStart(pos); - let r = f(self, pos); - self.lazy_state = LazyState::NoNode; - r +/// Helper trait to allow overloading `EncodeContext::lazy` for iterators. +trait EncodeContentsForLazy<T: ?Sized + LazyMeta> { + fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'tcx>) -> T::Meta; +} + +impl<T: Encodable> EncodeContentsForLazy<T> for &T { + fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'tcx>) { + self.encode(ecx).unwrap() } +} - fn emit_lazy_distance(&mut self, - position: usize, - min_size: usize) - -> Result<(), <Self as Encoder>::Error> { - let min_end = position + min_size; +impl<T: Encodable> EncodeContentsForLazy<T> for T { + fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'tcx>) { + self.encode(ecx).unwrap() + } +} + +impl<I, T> EncodeContentsForLazy<[T]> for I + where I: IntoIterator, + I::Item: EncodeContentsForLazy<T>, +{ + fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'tcx>) -> usize { + self.into_iter().map(|value| value.encode_contents_for_lazy(ecx)).count() + } +} + +impl<'tcx> EncodeContext<'tcx> { + fn emit_lazy_distance<T: ?Sized + LazyMeta>( + &mut self, + lazy: Lazy<T>, + ) -> Result<(), <Self as Encoder>::Error> { + let min_end = lazy.position + T::min_size(lazy.meta); let distance = match self.lazy_state { LazyState::NoNode => bug!("emit_lazy_distance: outside of a metadata node"), LazyState::NodeStart(start) => { @@ -254,48 +279,31 @@ impl<'tcx> EncodeContext<'tcx> { } LazyState::Previous(last_min_end) => { assert!( - last_min_end <= position, + last_min_end <= lazy.position, "make sure that the calls to `lazy*` \ are in the same order as the metadata fields", ); - position - last_min_end + lazy.position - last_min_end } }; self.lazy_state = LazyState::Previous(min_end); self.emit_usize(distance) } - pub fn lazy<T: Encodable>(&mut self, value: &T) -> Lazy<T> { - self.emit_node(|ecx, pos| { - value.encode(ecx).unwrap(); - - assert!(pos + Lazy::<T>::min_size() <= ecx.position()); - Lazy::with_position(pos) - }) - } - - pub fn lazy_seq<I, T>(&mut self, iter: I) -> LazySeq<T> - where I: IntoIterator<Item = T>, - T: Encodable - { - self.emit_node(|ecx, pos| { - let len = iter.into_iter().map(|value| value.encode(ecx).unwrap()).count(); + fn lazy<T: ?Sized + LazyMeta>( + &mut self, + value: impl EncodeContentsForLazy<T>, + ) -> Lazy<T> { + let pos = self.position(); - assert!(pos + LazySeq::<T>::min_size(len) <= ecx.position()); - LazySeq::with_position_and_length(pos, len) - }) - } + assert_eq!(self.lazy_state, LazyState::NoNode); + self.lazy_state = LazyState::NodeStart(pos); + let meta = value.encode_contents_for_lazy(self); + self.lazy_state = LazyState::NoNode; - pub fn lazy_seq_ref<'b, I, T>(&mut self, iter: I) -> LazySeq<T> - where I: IntoIterator<Item = &'b T>, - T: 'b + Encodable - { - self.emit_node(|ecx, pos| { - let len = iter.into_iter().map(|value| value.encode(ecx).unwrap()).count(); + assert!(pos + <T>::min_size(meta) <= self.position()); - assert!(pos + LazySeq::<T>::min_size(len) <= ecx.position()); - LazySeq::with_position_and_length(pos, len) - }) + Lazy::from_position_and_meta(pos, meta) } /// Emit the data for a `DefId` to the metadata. The function to @@ -312,7 +320,7 @@ impl<'tcx> EncodeContext<'tcx> { assert!(id.is_local()); let entry = op(self, data); - let entry = self.lazy(&entry); + let entry = self.lazy(entry); self.entries_index.record(id, entry); } @@ -333,7 +341,7 @@ impl<'tcx> EncodeContext<'tcx> { self.lazy(definitions.def_path_table()) } - fn encode_source_map(&mut self) -> LazySeq<syntax_pos::SourceFile> { + fn encode_source_map(&mut self) -> Lazy<[syntax_pos::SourceFile]> { let source_map = self.tcx.sess.source_map(); let all_source_files = source_map.files(); @@ -372,10 +380,12 @@ impl<'tcx> EncodeContext<'tcx> { }) .collect::<Vec<_>>(); - self.lazy_seq_ref(adapted.iter().map(|rc| &**rc)) + self.lazy(adapted.iter().map(|rc| &**rc)) } fn encode_crate_root(&mut self) -> Lazy<CrateRoot<'tcx>> { + let is_proc_macro = self.tcx.sess.crate_types.borrow().contains(&CrateType::ProcMacro); + let mut i = self.position(); let crate_deps = self.encode_crate_deps(); @@ -453,20 +463,26 @@ impl<'tcx> EncodeContext<'tcx> { } n = new_n; } - self.lazy_seq(interpret_alloc_index) + self.lazy(interpret_alloc_index) }; + i = self.position(); let entries_index = self.entries_index.write_index(&mut self.opaque); let entries_index_bytes = self.position() - i; + // Encode the proc macro data + i = self.position(); + let proc_macro_data = self.encode_proc_macros(); + let proc_macro_data_bytes = self.position() - i; + + let attrs = tcx.hir().krate_attrs(); - let is_proc_macro = tcx.sess.crate_types.borrow().contains(&CrateType::ProcMacro); let has_default_lib_allocator = attr::contains_name(&attrs, sym::default_lib_allocator); let has_global_allocator = *tcx.sess.has_global_allocator.get(); let has_panic_handler = *tcx.sess.has_panic_handler.try_get().unwrap_or(&false); - let root = self.lazy(&CrateRoot { + let root = self.lazy(CrateRoot { name: tcx.crate_name(LOCAL_CRATE), extra_filename: tcx.sess.opts.cg.extra_filename.clone(), triple: tcx.sess.opts.target_triple.clone(), @@ -484,6 +500,7 @@ impl<'tcx> EncodeContext<'tcx> { } else { None }, + proc_macro_data, proc_macro_stability: if is_proc_macro { tcx.lookup_stability(DefId::local(CRATE_DEF_INDEX)).map(|stab| stab.clone()) } else { @@ -532,6 +549,7 @@ impl<'tcx> EncodeContext<'tcx> { println!(" impl bytes: {}", impl_bytes); println!(" exp. symbols bytes: {}", exported_symbols_bytes); println!(" def-path table bytes: {}", def_path_table_bytes); + println!(" proc-macro-data-bytes: {}", proc_macro_data_bytes); println!(" item bytes: {}", item_bytes); println!(" entries index bytes: {}", entries_index_bytes); println!(" zero bytes: {}", zero_bytes); @@ -543,17 +561,17 @@ impl<'tcx> EncodeContext<'tcx> { } impl EncodeContext<'tcx> { - fn encode_variances_of(&mut self, def_id: DefId) -> LazySeq<ty::Variance> { + fn encode_variances_of(&mut self, def_id: DefId) -> Lazy<[ty::Variance]> { debug!("EncodeContext::encode_variances_of({:?})", def_id); let tcx = self.tcx; - self.lazy_seq_ref(&tcx.variances_of(def_id)[..]) + self.lazy(&tcx.variances_of(def_id)[..]) } fn encode_item_type(&mut self, def_id: DefId) -> Lazy<Ty<'tcx>> { let tcx = self.tcx; let ty = tcx.type_of(def_id); debug!("EncodeContext::encode_item_type({:?}) => {:?}", def_id, ty); - self.lazy(&ty) + self.lazy(ty) } fn encode_enum_variant_info( @@ -582,11 +600,11 @@ impl EncodeContext<'tcx> { let enum_vis = &tcx.hir().expect_item(enum_id).vis; Entry { - kind: EntryKind::Variant(self.lazy(&data)), - visibility: self.lazy(&ty::Visibility::from_hir(enum_vis, enum_id, tcx)), - span: self.lazy(&tcx.def_span(def_id)), + kind: EntryKind::Variant(self.lazy(data)), + visibility: self.lazy(ty::Visibility::from_hir(enum_vis, enum_id, tcx)), + span: self.lazy(tcx.def_span(def_id)), attributes: self.encode_attributes(&tcx.get_attrs(def_id)), - children: self.lazy_seq(variant.fields.iter().map(|f| { + children: self.lazy(variant.fields.iter().map(|f| { assert!(f.did.is_local()); f.did.index })), @@ -594,11 +612,11 @@ impl EncodeContext<'tcx> { deprecation: self.encode_deprecation(def_id), ty: Some(self.encode_item_type(def_id)), - inherent_impls: LazySeq::empty(), + inherent_impls: Lazy::empty(), variances: if variant.ctor_kind == CtorKind::Fn { self.encode_variances_of(def_id) } else { - LazySeq::empty() + Lazy::empty() }, generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), @@ -623,7 +641,7 @@ impl EncodeContext<'tcx> { discr: variant.discr, ctor: Some(def_id.index), ctor_sig: if variant.ctor_kind == CtorKind::Fn { - Some(self.lazy(&tcx.fn_sig(def_id))) + Some(self.lazy(tcx.fn_sig(def_id))) } else { None } @@ -639,20 +657,20 @@ impl EncodeContext<'tcx> { } Entry { - kind: EntryKind::Variant(self.lazy(&data)), - visibility: self.lazy(&ctor_vis), - span: self.lazy(&tcx.def_span(def_id)), - attributes: LazySeq::empty(), - children: LazySeq::empty(), + kind: EntryKind::Variant(self.lazy(data)), + visibility: self.lazy(ctor_vis), + span: self.lazy(tcx.def_span(def_id)), + attributes: Lazy::empty(), + children: Lazy::empty(), stability: self.encode_stability(def_id), deprecation: self.encode_deprecation(def_id), ty: Some(self.encode_item_type(def_id)), - inherent_impls: LazySeq::empty(), + inherent_impls: Lazy::empty(), variances: if variant.ctor_kind == CtorKind::Fn { self.encode_variances_of(def_id) } else { - LazySeq::empty() + Lazy::empty() }, generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), @@ -672,25 +690,25 @@ impl EncodeContext<'tcx> { let data = ModData { reexports: match tcx.module_exports(def_id) { - Some(exports) => self.lazy_seq_ref(exports), - _ => LazySeq::empty(), + Some(exports) => self.lazy(exports), + _ => Lazy::empty(), }, }; Entry { - kind: EntryKind::Mod(self.lazy(&data)), - visibility: self.lazy(&ty::Visibility::from_hir(vis, id, tcx)), - span: self.lazy(&tcx.def_span(def_id)), + kind: EntryKind::Mod(self.lazy(data)), + visibility: self.lazy(ty::Visibility::from_hir(vis, id, tcx)), + span: self.lazy(tcx.def_span(def_id)), attributes: self.encode_attributes(attrs), - children: self.lazy_seq(md.item_ids.iter().map(|item_id| { + children: self.lazy(md.item_ids.iter().map(|item_id| { tcx.hir().local_def_id(item_id.id).index })), stability: self.encode_stability(def_id), deprecation: self.encode_deprecation(def_id), ty: None, - inherent_impls: LazySeq::empty(), - variances: LazySeq::empty(), + inherent_impls: Lazy::empty(), + variances: Lazy::empty(), generics: None, predicates: None, predicates_defined_on: None, @@ -715,16 +733,16 @@ impl EncodeContext<'tcx> { Entry { kind: EntryKind::Field, - visibility: self.lazy(&field.vis), - span: self.lazy(&tcx.def_span(def_id)), + visibility: self.lazy(field.vis), + span: self.lazy(tcx.def_span(def_id)), attributes: self.encode_attributes(&variant_data.fields()[field_index].attrs), - children: LazySeq::empty(), + children: Lazy::empty(), stability: self.encode_stability(def_id), deprecation: self.encode_deprecation(def_id), ty: Some(self.encode_item_type(def_id)), - inherent_impls: LazySeq::empty(), - variances: LazySeq::empty(), + inherent_impls: Lazy::empty(), + variances: Lazy::empty(), generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), predicates_defined_on: None, @@ -744,7 +762,7 @@ impl EncodeContext<'tcx> { discr: variant.discr, ctor: Some(def_id.index), ctor_sig: if variant.ctor_kind == CtorKind::Fn { - Some(self.lazy(&tcx.fn_sig(def_id))) + Some(self.lazy(tcx.fn_sig(def_id))) } else { None } @@ -770,20 +788,20 @@ impl EncodeContext<'tcx> { let repr_options = get_repr_options(tcx, adt_def_id); Entry { - kind: EntryKind::Struct(self.lazy(&data), repr_options), - visibility: self.lazy(&ctor_vis), - span: self.lazy(&tcx.def_span(def_id)), - attributes: LazySeq::empty(), - children: LazySeq::empty(), + kind: EntryKind::Struct(self.lazy(data), repr_options), + visibility: self.lazy(ctor_vis), + span: self.lazy(tcx.def_span(def_id)), + attributes: Lazy::empty(), + children: Lazy::empty(), stability: self.encode_stability(def_id), deprecation: self.encode_deprecation(def_id), ty: Some(self.encode_item_type(def_id)), - inherent_impls: LazySeq::empty(), + inherent_impls: Lazy::empty(), variances: if variant.ctor_kind == CtorKind::Fn { self.encode_variances_of(def_id) } else { - LazySeq::empty() + Lazy::empty() }, generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), @@ -802,13 +820,13 @@ impl EncodeContext<'tcx> { fn encode_predicates(&mut self, def_id: DefId) -> Lazy<ty::GenericPredicates<'tcx>> { debug!("EncodeContext::encode_predicates({:?})", def_id); let tcx = self.tcx; - self.lazy(&tcx.predicates_of(def_id)) + self.lazy(&*tcx.predicates_of(def_id)) } fn encode_predicates_defined_on(&mut self, def_id: DefId) -> Lazy<ty::GenericPredicates<'tcx>> { debug!("EncodeContext::encode_predicates_defined_on({:?})", def_id); let tcx = self.tcx; - self.lazy(&tcx.predicates_defined_on(def_id)) + self.lazy(&*tcx.predicates_defined_on(def_id)) } fn encode_info_for_trait_item(&mut self, def_id: DefId) -> Entry<'tcx> { @@ -839,7 +857,7 @@ impl EncodeContext<'tcx> { let rendered = hir::print::to_string(self.tcx.hir(), |s| s.print_trait_item(ast_item)); - let rendered_const = self.lazy(&RenderedConst(rendered)); + let rendered_const = self.lazy(RenderedConst(rendered)); EntryKind::AssocConst(container, const_qualif, rendered_const) } @@ -856,12 +874,12 @@ impl EncodeContext<'tcx> { FnData { constness: hir::Constness::NotConst, arg_names, - sig: self.lazy(&tcx.fn_sig(def_id)), + sig: self.lazy(tcx.fn_sig(def_id)), } } else { bug!() }; - EntryKind::Method(self.lazy(&MethodData { + EntryKind::Method(self.lazy(MethodData { fn_data, container, has_self: trait_item.method_has_self_argument, @@ -873,10 +891,10 @@ impl EncodeContext<'tcx> { Entry { kind, - visibility: self.lazy(&trait_item.vis), - span: self.lazy(&ast_item.span), + visibility: self.lazy(trait_item.vis), + span: self.lazy(ast_item.span), attributes: self.encode_attributes(&ast_item.attrs), - children: LazySeq::empty(), + children: Lazy::empty(), stability: self.encode_stability(def_id), deprecation: self.encode_deprecation(def_id), @@ -894,11 +912,11 @@ impl EncodeContext<'tcx> { } ty::AssocKind::OpaqueTy => unreachable!(), }, - inherent_impls: LazySeq::empty(), + inherent_impls: Lazy::empty(), variances: if trait_item.kind == ty::AssocKind::Method { self.encode_variances_of(def_id) } else { - LazySeq::empty() + Lazy::empty() }, generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), @@ -952,12 +970,12 @@ impl EncodeContext<'tcx> { FnData { constness: sig.header.constness, arg_names: self.encode_fn_arg_names_for_body(body), - sig: self.lazy(&tcx.fn_sig(def_id)), + sig: self.lazy(tcx.fn_sig(def_id)), } } else { bug!() }; - EntryKind::Method(self.lazy(&MethodData { + EntryKind::Method(self.lazy(MethodData { fn_data, container, has_self: impl_item.method_has_self_argument, @@ -985,19 +1003,19 @@ impl EncodeContext<'tcx> { Entry { kind, - visibility: self.lazy(&impl_item.vis), - span: self.lazy(&ast_item.span), + visibility: self.lazy(impl_item.vis), + span: self.lazy(ast_item.span), attributes: self.encode_attributes(&ast_item.attrs), - children: LazySeq::empty(), + children: Lazy::empty(), stability: self.encode_stability(def_id), deprecation: self.encode_deprecation(def_id), ty: Some(self.encode_item_type(def_id)), - inherent_impls: LazySeq::empty(), + inherent_impls: Lazy::empty(), variances: if impl_item.kind == ty::AssocKind::Method { self.encode_variances_of(def_id) } else { - LazySeq::empty() + Lazy::empty() }, generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), @@ -1008,10 +1026,10 @@ impl EncodeContext<'tcx> { } fn encode_fn_arg_names_for_body(&mut self, body_id: hir::BodyId) - -> LazySeq<ast::Name> { + -> Lazy<[ast::Name]> { self.tcx.dep_graph.with_ignore(|| { let body = self.tcx.hir().body(body_id); - self.lazy_seq(body.arguments.iter().map(|arg| { + self.lazy(body.arguments.iter().map(|arg| { match arg.pat.node { PatKind::Binding(_, _, ident, _) => ident.name, _ => kw::Invalid, @@ -1020,28 +1038,28 @@ impl EncodeContext<'tcx> { }) } - fn encode_fn_arg_names(&mut self, param_names: &[ast::Ident]) -> LazySeq<ast::Name> { - self.lazy_seq(param_names.iter().map(|ident| ident.name)) + fn encode_fn_arg_names(&mut self, param_names: &[ast::Ident]) -> Lazy<[ast::Name]> { + self.lazy(param_names.iter().map(|ident| ident.name)) } fn encode_optimized_mir(&mut self, def_id: DefId) -> Option<Lazy<mir::Body<'tcx>>> { debug!("EntryBuilder::encode_mir({:?})", def_id); if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id) { let mir = self.tcx.optimized_mir(def_id); - Some(self.lazy(&mir)) + Some(self.lazy(mir)) } else { None } } // Encodes the inherent implementations of a structure, enumeration, or trait. - fn encode_inherent_implementations(&mut self, def_id: DefId) -> LazySeq<DefIndex> { + fn encode_inherent_implementations(&mut self, def_id: DefId) -> Lazy<[DefIndex]> { debug!("EncodeContext::encode_inherent_implementations({:?})", def_id); let implementations = self.tcx.inherent_impls(def_id); if implementations.is_empty() { - LazySeq::empty() + Lazy::empty() } else { - self.lazy_seq(implementations.iter().map(|&def_id| { + self.lazy(implementations.iter().map(|&def_id| { assert!(def_id.is_local()); def_id.index })) @@ -1055,7 +1073,7 @@ impl EncodeContext<'tcx> { fn encode_deprecation(&mut self, def_id: DefId) -> Option<Lazy<attr::Deprecation>> { debug!("EncodeContext::encode_deprecation({:?})", def_id); - self.tcx.lookup_deprecation(def_id).map(|depr| self.lazy(&depr)) + self.tcx.lookup_deprecation(def_id).map(|depr| self.lazy(depr)) } fn encode_rendered_const_for_body(&mut self, body_id: hir::BodyId) -> Lazy<RenderedConst> { @@ -1084,10 +1102,10 @@ impl EncodeContext<'tcx> { let data = FnData { constness: header.constness, arg_names: self.encode_fn_arg_names_for_body(body), - sig: self.lazy(&tcx.fn_sig(def_id)), + sig: self.lazy(tcx.fn_sig(def_id)), }; - EntryKind::Fn(self.lazy(&data)) + EntryKind::Fn(self.lazy(data)) } hir::ItemKind::Mod(ref m) => { return self.encode_info_for_mod((item.hir_id, m, &item.attrs, &item.vis)); @@ -1108,7 +1126,7 @@ impl EncodeContext<'tcx> { let repr_options = get_repr_options(tcx, def_id); - EntryKind::Struct(self.lazy(&VariantData { + EntryKind::Struct(self.lazy(VariantData { ctor_kind: variant.ctor_kind, discr: variant.discr, ctor, @@ -1119,7 +1137,7 @@ impl EncodeContext<'tcx> { let variant = tcx.adt_def(def_id).non_enum_variant(); let repr_options = get_repr_options(tcx, def_id); - EntryKind::Union(self.lazy(&VariantData { + EntryKind::Union(self.lazy(VariantData { ctor_kind: variant.ctor_kind, discr: variant.discr, ctor: None, @@ -1156,10 +1174,10 @@ impl EncodeContext<'tcx> { defaultness, parent_impl: parent, coerce_unsized_info, - trait_ref: trait_ref.map(|trait_ref| self.lazy(&trait_ref)), + trait_ref: trait_ref.map(|trait_ref| self.lazy(trait_ref)), }; - EntryKind::Impl(self.lazy(&data)) + EntryKind::Impl(self.lazy(data)) } hir::ItemKind::Trait(..) => { let trait_def = tcx.trait_def(def_id); @@ -1168,17 +1186,17 @@ impl EncodeContext<'tcx> { paren_sugar: trait_def.paren_sugar, has_auto_impl: tcx.trait_is_auto(def_id), is_marker: trait_def.is_marker, - super_predicates: self.lazy(&tcx.super_predicates_of(def_id)), + super_predicates: self.lazy(&*tcx.super_predicates_of(def_id)), }; - EntryKind::Trait(self.lazy(&data)) + EntryKind::Trait(self.lazy(data)) } hir::ItemKind::TraitAlias(..) => { let data = TraitAliasData { - super_predicates: self.lazy(&tcx.super_predicates_of(def_id)), + super_predicates: self.lazy(&*tcx.super_predicates_of(def_id)), }; - EntryKind::TraitAlias(self.lazy(&data)) + EntryKind::TraitAlias(self.lazy(data)) } hir::ItemKind::ExternCrate(_) | hir::ItemKind::Use(..) => bug!("cannot encode info for item {:?}", item), @@ -1186,19 +1204,19 @@ impl EncodeContext<'tcx> { Entry { kind, - visibility: self.lazy(&ty::Visibility::from_hir(&item.vis, item.hir_id, tcx)), - span: self.lazy(&item.span), + visibility: self.lazy(ty::Visibility::from_hir(&item.vis, item.hir_id, tcx)), + span: self.lazy(item.span), attributes: self.encode_attributes(&item.attrs), children: match item.node { hir::ItemKind::ForeignMod(ref fm) => { - self.lazy_seq(fm.items + self.lazy(fm.items .iter() .map(|foreign_item| tcx.hir().local_def_id( foreign_item.hir_id).index)) } hir::ItemKind::Enum(..) => { let def = self.tcx.adt_def(def_id); - self.lazy_seq(def.variants.iter().map(|v| { + self.lazy(def.variants.iter().map(|v| { assert!(v.def_id.is_local()); v.def_id.index })) @@ -1206,19 +1224,19 @@ impl EncodeContext<'tcx> { hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => { let def = self.tcx.adt_def(def_id); - self.lazy_seq(def.non_enum_variant().fields.iter().map(|f| { + self.lazy(def.non_enum_variant().fields.iter().map(|f| { assert!(f.did.is_local()); f.did.index })) } hir::ItemKind::Impl(..) | hir::ItemKind::Trait(..) => { - self.lazy_seq(tcx.associated_item_def_ids(def_id).iter().map(|&def_id| { + self.lazy(tcx.associated_item_def_ids(def_id).iter().map(|&def_id| { assert!(def_id.is_local()); def_id.index })) } - _ => LazySeq::empty(), + _ => Lazy::empty(), }, stability: self.encode_stability(def_id), deprecation: self.encode_deprecation(def_id), @@ -1241,7 +1259,7 @@ impl EncodeContext<'tcx> { hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) | hir::ItemKind::Fn(..) => self.encode_variances_of(def_id), - _ => LazySeq::empty(), + _ => Lazy::empty(), }, generics: match item.node { hir::ItemKind::Static(..) | @@ -1314,20 +1332,20 @@ impl EncodeContext<'tcx> { use syntax::print::pprust; let def_id = self.tcx.hir().local_def_id(macro_def.hir_id); Entry { - kind: EntryKind::MacroDef(self.lazy(&MacroDef { + kind: EntryKind::MacroDef(self.lazy(MacroDef { body: pprust::tokens_to_string(macro_def.body.clone()), legacy: macro_def.legacy, })), - visibility: self.lazy(&ty::Visibility::Public), - span: self.lazy(¯o_def.span), + visibility: self.lazy(ty::Visibility::Public), + span: self.lazy(macro_def.span), attributes: self.encode_attributes(¯o_def.attrs), stability: self.encode_stability(def_id), deprecation: self.encode_deprecation(def_id), - children: LazySeq::empty(), + children: Lazy::empty(), ty: None, - inherent_impls: LazySeq::empty(), - variances: LazySeq::empty(), + inherent_impls: Lazy::empty(), + variances: Lazy::empty(), generics: None, predicates: None, predicates_defined_on: None, @@ -1344,15 +1362,15 @@ impl EncodeContext<'tcx> { let tcx = self.tcx; Entry { kind: entry_kind, - visibility: self.lazy(&ty::Visibility::Public), - span: self.lazy(&tcx.def_span(def_id)), - attributes: LazySeq::empty(), - children: LazySeq::empty(), + visibility: self.lazy(ty::Visibility::Public), + span: self.lazy(tcx.def_span(def_id)), + attributes: Lazy::empty(), + children: Lazy::empty(), stability: None, deprecation: None, ty: if encode_type { Some(self.encode_item_type(def_id)) } else { None }, - inherent_impls: LazySeq::empty(), - variances: LazySeq::empty(), + inherent_impls: Lazy::empty(), + variances: Lazy::empty(), generics: None, predicates: None, predicates_defined_on: None, @@ -1389,13 +1407,13 @@ impl EncodeContext<'tcx> { let data = GeneratorData { layout: layout.clone(), }; - EntryKind::Generator(self.lazy(&data)) + EntryKind::Generator(self.lazy(data)) } ty::Closure(def_id, substs) => { let sig = substs.closure_sig(def_id, self.tcx); - let data = ClosureData { sig: self.lazy(&sig) }; - EntryKind::Closure(self.lazy(&data)) + let data = ClosureData { sig: self.lazy(sig) }; + EntryKind::Closure(self.lazy(data)) } _ => bug!("closure that is neither generator nor closure") @@ -1403,16 +1421,16 @@ impl EncodeContext<'tcx> { Entry { kind, - visibility: self.lazy(&ty::Visibility::Public), - span: self.lazy(&tcx.def_span(def_id)), + visibility: self.lazy(ty::Visibility::Public), + span: self.lazy(tcx.def_span(def_id)), attributes: self.encode_attributes(&tcx.get_attrs(def_id)), - children: LazySeq::empty(), + children: Lazy::empty(), stability: None, deprecation: None, ty: Some(self.encode_item_type(def_id)), - inherent_impls: LazySeq::empty(), - variances: LazySeq::empty(), + inherent_impls: Lazy::empty(), + variances: Lazy::empty(), generics: Some(self.encode_generics(def_id)), predicates: None, predicates_defined_on: None, @@ -1431,16 +1449,16 @@ impl EncodeContext<'tcx> { Entry { kind: EntryKind::Const(self.const_qualif(mir, body_id), const_data), - visibility: self.lazy(&ty::Visibility::Public), - span: self.lazy(&tcx.def_span(def_id)), - attributes: LazySeq::empty(), - children: LazySeq::empty(), + visibility: self.lazy(ty::Visibility::Public), + span: self.lazy(tcx.def_span(def_id)), + attributes: Lazy::empty(), + children: Lazy::empty(), stability: None, deprecation: None, ty: Some(self.encode_item_type(def_id)), - inherent_impls: LazySeq::empty(), - variances: LazySeq::empty(), + inherent_impls: Lazy::empty(), + variances: Lazy::empty(), generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), predicates_defined_on: None, @@ -1449,21 +1467,37 @@ impl EncodeContext<'tcx> { } } - fn encode_attributes(&mut self, attrs: &[ast::Attribute]) -> LazySeq<ast::Attribute> { - self.lazy_seq_ref(attrs) + fn encode_attributes(&mut self, attrs: &[ast::Attribute]) -> Lazy<[ast::Attribute]> { + self.lazy(attrs) } - fn encode_native_libraries(&mut self) -> LazySeq<NativeLibrary> { + fn encode_native_libraries(&mut self) -> Lazy<[NativeLibrary]> { let used_libraries = self.tcx.native_libraries(LOCAL_CRATE); - self.lazy_seq(used_libraries.iter().cloned()) + self.lazy(used_libraries.iter().cloned()) } - fn encode_foreign_modules(&mut self) -> LazySeq<ForeignModule> { + fn encode_foreign_modules(&mut self) -> Lazy<[ForeignModule]> { let foreign_modules = self.tcx.foreign_modules(LOCAL_CRATE); - self.lazy_seq(foreign_modules.iter().cloned()) + self.lazy(foreign_modules.iter().cloned()) + } + + fn encode_proc_macros(&mut self) -> Option<Lazy<[DefIndex]>> { + let is_proc_macro = self.tcx.sess.crate_types.borrow().contains(&CrateType::ProcMacro); + if is_proc_macro { + let tcx = self.tcx; + Some(self.lazy(tcx.hir().krate().items.values().filter_map(|item| { + if item.attrs.iter().any(|attr| is_proc_macro_attr(attr)) { + Some(item.hir_id.owner) + } else { + None + } + }))) + } else { + None + } } - fn encode_crate_deps(&mut self) -> LazySeq<CrateDep> { + fn encode_crate_deps(&mut self) -> Lazy<[CrateDep]> { let crates = self.tcx.crates(); let mut deps = crates @@ -1494,20 +1528,20 @@ impl EncodeContext<'tcx> { // the assumption that they are numbered 1 to n. // FIXME (#2166): This is not nearly enough to support correct versioning // but is enough to get transitive crate dependencies working. - self.lazy_seq_ref(deps.iter().map(|&(_, ref dep)| dep)) + self.lazy(deps.iter().map(|&(_, ref dep)| dep)) } - fn encode_lib_features(&mut self) -> LazySeq<(ast::Name, Option<ast::Name>)> { + fn encode_lib_features(&mut self) -> Lazy<[(ast::Name, Option<ast::Name>)]> { let tcx = self.tcx; let lib_features = tcx.lib_features(); - self.lazy_seq(lib_features.to_vec()) + self.lazy(lib_features.to_vec()) } - fn encode_lang_items(&mut self) -> LazySeq<(DefIndex, usize)> { + fn encode_lang_items(&mut self) -> Lazy<[(DefIndex, usize)]> { let tcx = self.tcx; let lang_items = tcx.lang_items(); let lang_items = lang_items.items().iter(); - self.lazy_seq(lang_items.enumerate().filter_map(|(i, &opt_def_id)| { + self.lazy(lang_items.enumerate().filter_map(|(i, &opt_def_id)| { if let Some(def_id) = opt_def_id { if def_id.is_local() { return Some((def_id.index, i)); @@ -1517,13 +1551,13 @@ impl EncodeContext<'tcx> { })) } - fn encode_lang_items_missing(&mut self) -> LazySeq<lang_items::LangItem> { + fn encode_lang_items_missing(&mut self) -> Lazy<[lang_items::LangItem]> { let tcx = self.tcx; - self.lazy_seq_ref(&tcx.lang_items().missing) + self.lazy(&tcx.lang_items().missing) } /// Encodes an index, mapping each trait to its (local) implementations. - fn encode_impls(&mut self) -> LazySeq<TraitImpls> { + fn encode_impls(&mut self) -> Lazy<[TraitImpls]> { debug!("EncodeContext::encode_impls()"); let tcx = self.tcx; let mut visitor = ImplVisitor { @@ -1549,12 +1583,12 @@ impl EncodeContext<'tcx> { TraitImpls { trait_id: (trait_def_id.krate.as_u32(), trait_def_id.index), - impls: self.lazy_seq_ref(&impls), + impls: self.lazy(&impls), } }) .collect(); - self.lazy_seq_ref(&all_impls) + self.lazy(&all_impls) } // Encodes all symbols exported from this crate into the metadata. @@ -1565,12 +1599,12 @@ impl EncodeContext<'tcx> { // definition (as that's not defined in this crate). fn encode_exported_symbols(&mut self, exported_symbols: &[(ExportedSymbol<'tcx>, SymbolExportLevel)]) - -> LazySeq<(ExportedSymbol<'tcx>, SymbolExportLevel)> { + -> Lazy<[(ExportedSymbol<'tcx>, SymbolExportLevel)]> { // The metadata symbol name is special. It should not show up in // downstream crates. let metadata_symbol_name = SymbolName::new(&metadata_symbol_name(self.tcx)); - self.lazy_seq(exported_symbols + self.lazy(exported_symbols .iter() .filter(|&&(ref exported_symbol, _)| { match *exported_symbol { @@ -1583,10 +1617,10 @@ impl EncodeContext<'tcx> { .cloned()) } - fn encode_dylib_dependency_formats(&mut self) -> LazySeq<Option<LinkagePreference>> { + fn encode_dylib_dependency_formats(&mut self) -> Lazy<[Option<LinkagePreference>]> { match self.tcx.sess.dependency_formats.borrow().get(&config::CrateType::Dylib) { Some(arr) => { - self.lazy_seq(arr.iter().map(|slot| { + self.lazy(arr.iter().map(|slot| { match *slot { Linkage::NotLinked | Linkage::IncludedFromDylib => None, @@ -1596,7 +1630,7 @@ impl EncodeContext<'tcx> { } })) } - None => LazySeq::empty(), + None => Lazy::empty(), } } @@ -1612,9 +1646,9 @@ impl EncodeContext<'tcx> { let data = FnData { constness: hir::Constness::NotConst, arg_names: self.encode_fn_arg_names(names), - sig: self.lazy(&tcx.fn_sig(def_id)), + sig: self.lazy(tcx.fn_sig(def_id)), }; - EntryKind::ForeignFn(self.lazy(&data)) + EntryKind::ForeignFn(self.lazy(data)) } hir::ForeignItemKind::Static(_, hir::MutMutable) => EntryKind::ForeignMutStatic, hir::ForeignItemKind::Static(_, hir::MutImmutable) => EntryKind::ForeignImmStatic, @@ -1623,18 +1657,18 @@ impl EncodeContext<'tcx> { Entry { kind, - visibility: self.lazy(&ty::Visibility::from_hir(&nitem.vis, nitem.hir_id, tcx)), - span: self.lazy(&nitem.span), + visibility: self.lazy(ty::Visibility::from_hir(&nitem.vis, nitem.hir_id, tcx)), + span: self.lazy(nitem.span), attributes: self.encode_attributes(&nitem.attrs), - children: LazySeq::empty(), + children: Lazy::empty(), stability: self.encode_stability(def_id), deprecation: self.encode_deprecation(def_id), ty: Some(self.encode_item_type(def_id)), - inherent_impls: LazySeq::empty(), + inherent_impls: Lazy::empty(), variances: match nitem.node { hir::ForeignItemKind::Fn(..) => self.encode_variances_of(def_id), - _ => LazySeq::empty(), + _ => Lazy::empty(), }, generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), @@ -1676,7 +1710,7 @@ impl Visitor<'tcx> for EncodeContext<'tcx> { id: hir::HirId) { intravisit::walk_variant(self, v, g, id); - if let Some(ref discr) = v.node.disr_expr { + if let Some(ref discr) = v.disr_expr { let def_id = self.tcx.hir().local_def_id(discr.hir_id); self.record(def_id, EncodeContext::encode_info_for_anon_const, def_id); } diff --git a/src/librustc_metadata/index.rs b/src/librustc_metadata/index.rs index dd2f59922ef..6f248f22cf2 100644 --- a/src/librustc_metadata/index.rs +++ b/src/librustc_metadata/index.rs @@ -108,18 +108,18 @@ impl Index<'tcx> { position.write_to_bytes_at(positions, array_index) } - pub fn write_index(&self, buf: &mut Encoder) -> LazySeq<Self> { + pub fn write_index(&self, buf: &mut Encoder) -> Lazy<[Self]> { let pos = buf.position(); // First we write the length of the lower range ... buf.emit_raw_bytes(&(self.positions.len() as u32 / 4).to_le_bytes()); // ... then the values. buf.emit_raw_bytes(&self.positions); - LazySeq::with_position_and_length(pos as usize, self.positions.len() / 4 + 1) + Lazy::from_position_and_meta(pos as usize, self.positions.len() / 4 + 1) } } -impl LazySeq<Index<'tcx>> { +impl Lazy<[Index<'tcx>]> { /// Given the metadata, extract out the offset of a particular /// DefIndex (if any). #[inline(never)] @@ -127,7 +127,7 @@ impl LazySeq<Index<'tcx>> { let bytes = &bytes[self.position..]; debug!("Index::lookup: index={:?} len={:?}", def_index, - self.len); + self.meta); let position = u32::read_from_bytes_at(bytes, 1 + def_index.index()); if position == u32::MAX { @@ -135,7 +135,7 @@ impl LazySeq<Index<'tcx>> { None } else { debug!("Index::lookup: position={:?}", position); - Some(Lazy::with_position(position as usize)) + Some(Lazy::from_position(position as usize)) } } } diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs index 3832c8ee227..ceba7cf0fe0 100644 --- a/src/librustc_metadata/locator.rs +++ b/src/librustc_metadata/locator.rs @@ -716,7 +716,9 @@ impl<'a> Context<'a> { let root = metadata.get_root(); if let Some(is_proc_macro) = self.is_proc_macro { - if root.proc_macro_decls_static.is_some() != is_proc_macro { + if root.proc_macro_data.is_some() != is_proc_macro { + info!("Rejecting via proc macro: expected {} got {}", + is_proc_macro, root.proc_macro_data.is_some()); return None; } } diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index c0ac6915933..f37877b437e 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -41,6 +41,33 @@ pub const METADATA_VERSION: u8 = 4; pub const METADATA_HEADER: &[u8; 12] = &[0, 0, 0, 0, b'r', b'u', b's', b't', 0, 0, 0, METADATA_VERSION]; +/// Additional metadata for a `Lazy<T>` where `T` may not be `Sized`, +/// e.g. for `Lazy<[T]>`, this is the length (count of `T` values). +pub trait LazyMeta { + type Meta: Copy + 'static; + + /// Returns the minimum encoded size. + // FIXME(eddyb) Give better estimates for certain types. + fn min_size(meta: Self::Meta) -> usize; +} + +impl<T> LazyMeta for T { + type Meta = (); + + fn min_size(_: ()) -> usize { + assert_ne!(std::mem::size_of::<T>(), 0); + 1 + } +} + +impl<T> LazyMeta for [T] { + type Meta = usize; + + fn min_size(len: usize) -> usize { + len * T::min_size(()) + } +} + /// A value of type T referred to by its absolute position /// in the metadata, and which can be decoded lazily. /// @@ -56,40 +83,8 @@ pub const METADATA_HEADER: &[u8; 12] = /// Distances start at 1, as 0-byte nodes are invalid. /// Also invalid are nodes being referred in a different /// order than they were encoded in. -#[must_use] -pub struct Lazy<T> { - pub position: usize, - _marker: PhantomData<T>, -} - -impl<T> Lazy<T> { - pub fn with_position(position: usize) -> Lazy<T> { - Lazy { - position, - _marker: PhantomData, - } - } - - /// Returns the minimum encoded size of a value of type `T`. - // FIXME(eddyb) Give better estimates for certain types. - pub fn min_size() -> usize { - 1 - } -} - -impl<T> Copy for Lazy<T> {} -impl<T> Clone for Lazy<T> { - fn clone(&self) -> Self { - *self - } -} - -impl<T> rustc_serialize::UseSpecializedEncodable for Lazy<T> {} -impl<T> rustc_serialize::UseSpecializedDecodable for Lazy<T> {} - -/// A sequence of type T referred to by its absolute position -/// in the metadata and length, and which can be decoded lazily. -/// The sequence is a single node for the purposes of `Lazy`. +/// +/// # Sequences (`Lazy<[T]>`) /// /// Unlike `Lazy<Vec<T>>`, the length is encoded next to the /// position, not at the position, which means that the length @@ -100,54 +95,62 @@ impl<T> rustc_serialize::UseSpecializedDecodable for Lazy<T> {} /// the minimal distance the length of the sequence, i.e. /// it's assumed there's no 0-byte element in the sequence. #[must_use] -pub struct LazySeq<T> { - pub len: usize, +// FIXME(#59875) the `Meta` parameter only exists to dodge +// invariance wrt `T` (coming from the `meta: T::Meta` field). +pub struct Lazy<T, Meta = <T as LazyMeta>::Meta> + where T: ?Sized + LazyMeta<Meta = Meta>, + Meta: 'static + Copy, +{ pub position: usize, + pub meta: Meta, _marker: PhantomData<T>, } -impl<T> LazySeq<T> { - pub fn empty() -> LazySeq<T> { - LazySeq::with_position_and_length(0, 0) - } - - pub fn with_position_and_length(position: usize, len: usize) -> LazySeq<T> { - LazySeq { - len, +impl<T: ?Sized + LazyMeta> Lazy<T> { + pub fn from_position_and_meta(position: usize, meta: T::Meta) -> Lazy<T> { + Lazy { position, + meta, _marker: PhantomData, } } +} - /// Returns the minimum encoded size of `length` values of type `T`. - pub fn min_size(length: usize) -> usize { - length +impl<T> Lazy<T> { + pub fn from_position(position: usize) -> Lazy<T> { + Lazy::from_position_and_meta(position, ()) } } -impl<T> Copy for LazySeq<T> {} -impl<T> Clone for LazySeq<T> { +impl<T> Lazy<[T]> { + pub fn empty() -> Lazy<[T]> { + Lazy::from_position_and_meta(0, 0) + } +} + +impl<T: ?Sized + LazyMeta> Copy for Lazy<T> {} +impl<T: ?Sized + LazyMeta> Clone for Lazy<T> { fn clone(&self) -> Self { *self } } -impl<T> rustc_serialize::UseSpecializedEncodable for LazySeq<T> {} -impl<T> rustc_serialize::UseSpecializedDecodable for LazySeq<T> {} +impl<T: ?Sized + LazyMeta> rustc_serialize::UseSpecializedEncodable for Lazy<T> {} +impl<T: ?Sized + LazyMeta> rustc_serialize::UseSpecializedDecodable for Lazy<T> {} -/// Encoding / decoding state for `Lazy` and `LazySeq`. +/// Encoding / decoding state for `Lazy`. #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum LazyState { /// Outside of a metadata node. NoNode, - /// Inside a metadata node, and before any `Lazy` or `LazySeq`. + /// Inside a metadata node, and before any `Lazy`. /// The position is that of the node itself. NodeStart(usize), - /// Inside a metadata node, with a previous `Lazy` or `LazySeq`. + /// Inside a metadata node, with a previous `Lazy`. /// The position is a conservative estimate of where that - /// previous `Lazy` / `LazySeq` would end (see their comments). + /// previous `Lazy` would end (see their comments). Previous(usize), } @@ -167,20 +170,24 @@ pub struct CrateRoot<'tcx> { pub proc_macro_decls_static: Option<DefIndex>, pub proc_macro_stability: Option<attr::Stability>, - pub crate_deps: LazySeq<CrateDep>, - pub dylib_dependency_formats: LazySeq<Option<LinkagePreference>>, - pub lib_features: LazySeq<(Symbol, Option<Symbol>)>, - pub lang_items: LazySeq<(DefIndex, usize)>, - pub lang_items_missing: LazySeq<lang_items::LangItem>, - pub native_libraries: LazySeq<NativeLibrary>, - pub foreign_modules: LazySeq<ForeignModule>, - pub source_map: LazySeq<syntax_pos::SourceFile>, + pub crate_deps: Lazy<[CrateDep]>, + pub dylib_dependency_formats: Lazy<[Option<LinkagePreference>]>, + pub lib_features: Lazy<[(Symbol, Option<Symbol>)]>, + pub lang_items: Lazy<[(DefIndex, usize)]>, + pub lang_items_missing: Lazy<[lang_items::LangItem]>, + pub native_libraries: Lazy<[NativeLibrary]>, + pub foreign_modules: Lazy<[ForeignModule]>, + pub source_map: Lazy<[syntax_pos::SourceFile]>, pub def_path_table: Lazy<hir::map::definitions::DefPathTable>, - pub impls: LazySeq<TraitImpls>, - pub exported_symbols: LazySeq<(ExportedSymbol<'tcx>, SymbolExportLevel)>, - pub interpret_alloc_index: LazySeq<u32>, + pub impls: Lazy<[TraitImpls]>, + pub exported_symbols: Lazy<[(ExportedSymbol<'tcx>, SymbolExportLevel)]>, + pub interpret_alloc_index: Lazy<[u32]>, + + pub entries_index: Lazy<[index::Index<'tcx>]>, - pub entries_index: LazySeq<index::Index<'tcx>>, + /// The DefIndex's of any proc macros delcared by + /// this crate + pub proc_macro_data: Option<Lazy<[DefIndex]>>, pub compiler_builtins: bool, pub needs_allocator: bool, @@ -203,7 +210,7 @@ pub struct CrateDep { #[derive(RustcEncodable, RustcDecodable)] pub struct TraitImpls { pub trait_id: (u32, DefIndex), - pub impls: LazySeq<DefIndex>, + pub impls: Lazy<[DefIndex]>, } #[derive(RustcEncodable, RustcDecodable)] @@ -211,14 +218,14 @@ pub struct Entry<'tcx> { pub kind: EntryKind<'tcx>, pub visibility: Lazy<ty::Visibility>, pub span: Lazy<Span>, - pub attributes: LazySeq<ast::Attribute>, - pub children: LazySeq<DefIndex>, + pub attributes: Lazy<[ast::Attribute]>, + pub children: Lazy<[DefIndex]>, pub stability: Option<Lazy<attr::Stability>>, pub deprecation: Option<Lazy<attr::Deprecation>>, pub ty: Option<Lazy<Ty<'tcx>>>, - pub inherent_impls: LazySeq<DefIndex>, - pub variances: LazySeq<ty::Variance>, + pub inherent_impls: Lazy<[DefIndex]>, + pub variances: Lazy<[ty::Variance]>, pub generics: Option<Lazy<ty::Generics>>, pub predicates: Option<Lazy<ty::GenericPredicates<'tcx>>>, pub predicates_defined_on: Option<Lazy<ty::GenericPredicates<'tcx>>>, @@ -274,7 +281,7 @@ pub struct RenderedConst(pub String); #[derive(RustcEncodable, RustcDecodable)] pub struct ModData { - pub reexports: LazySeq<def::Export<hir::HirId>>, + pub reexports: Lazy<[def::Export<hir::HirId>]>, } #[derive(RustcEncodable, RustcDecodable)] @@ -286,7 +293,7 @@ pub struct MacroDef { #[derive(RustcEncodable, RustcDecodable)] pub struct FnData<'tcx> { pub constness: hir::Constness, - pub arg_names: LazySeq<ast::Name>, + pub arg_names: Lazy<[ast::Name]>, pub sig: Lazy<ty::PolyFnSig<'tcx>>, } diff --git a/src/librustc_mir/borrow_check/conflict_errors.rs b/src/librustc_mir/borrow_check/conflict_errors.rs index 4217a29bc66..247783c420e 100644 --- a/src/librustc_mir/borrow_check/conflict_errors.rs +++ b/src/librustc_mir/borrow_check/conflict_errors.rs @@ -1190,7 +1190,16 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); let suggestion = match tcx.sess.source_map().span_to_snippet(args_span) { - Ok(string) => format!("move {}", string), + Ok(mut string) => { + if string.starts_with("async ") { + string.insert_str(6, "move "); + } else if string.starts_with("async|") { + string.insert_str(5, " move"); + } else { + string.insert_str(0, "move "); + }; + string + }, Err(_) => "move |<args>| <body>".to_string() }; 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 3f5b2f4bce7..ca68b9e31b6 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 @@ -578,7 +578,8 @@ impl<'tcx> RegionInferenceContext<'tcx> { }) } - hir::LifetimeName::Implicit => { + hir::LifetimeName::ImplicitObjectLifetimeDefault + | hir::LifetimeName::Implicit => { // In this case, the user left off the lifetime; so // they wrote something like: // diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 70d6c15d8e2..9ff0c6ca6a5 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -272,12 +272,11 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) { self.super_constant(constant, location); - self.sanitize_constant(constant, location); - self.sanitize_type(constant, constant.ty); + self.sanitize_type(constant, constant.literal.ty); if let Some(annotation_index) = constant.user_ty { if let Err(terr) = self.cx.relate_type_and_user_type( - constant.ty, + constant.literal.ty, ty::Variance::Invariant, &UserTypeProjection { base: annotation_index, projs: vec![], }, location.to_locations(), @@ -289,7 +288,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { constant, "bad constant user type {:?} vs {:?}: {:?}", annotation, - constant.ty, + constant.literal.ty, terr, ); } @@ -299,7 +298,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { location.to_locations(), ConstraintCategory::Boring, self.cx.param_env.and(type_op::ascribe_user_type::AscribeUserType::new( - constant.ty, def_id, UserSubsts { substs, user_self_ty: None }, + constant.literal.ty, def_id, UserSubsts { substs, user_self_ty: None }, )), ) { span_mirbug!( @@ -403,41 +402,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { } } - /// Checks that the constant's `ty` field matches up with what would be - /// expected from its literal. Unevaluated constants and well-formed - /// constraints are checked by `visit_constant`. - fn sanitize_constant(&mut self, constant: &Constant<'tcx>, location: Location) { - debug!( - "sanitize_constant(constant={:?}, location={:?})", - constant, location - ); - - let literal = constant.literal; - - if let ConstValue::Unevaluated(..) = literal.val { - return; - } - - debug!("sanitize_constant: expected_ty={:?}", literal.ty); - - if let Err(terr) = self.cx.eq_types( - literal.ty, - constant.ty, - location.to_locations(), - ConstraintCategory::Boring, - ) { - span_mirbug!( - self, - constant, - "constant {:?} should have type {:?} but has {:?} ({:?})", - constant, - literal.ty, - constant.ty, - terr, - ); - } - } - /// Checks that the types internal to the `place` match up with /// what would be expected. fn sanitize_place( diff --git a/src/librustc_mir/build/expr/as_constant.rs b/src/librustc_mir/build/expr/as_constant.rs index 5197981a85c..39bdc871d83 100644 --- a/src/librustc_mir/build/expr/as_constant.rs +++ b/src/librustc_mir/build/expr/as_constant.rs @@ -38,9 +38,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { inferred_ty: ty, }) }); + assert_eq!(literal.ty, ty); Constant { span, - ty, user_ty, literal, } diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index ec061e74535..1a186fa932d 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -591,7 +591,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let n = (!0u128) >> (128 - bits); let literal = ty::Const::from_bits(self.hir.tcx(), n, param_ty); - self.literal_operand(span, ty, literal) + self.literal_operand(span, literal) } // Helper to get the minimum value of the appropriate type @@ -602,6 +602,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let n = 1 << (bits - 1); let literal = ty::Const::from_bits(self.hir.tcx(), n, param_ty); - self.literal_operand(span, ty, literal) + self.literal_operand(span, literal) } } diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index 02ab53fe8c1..889861b8567 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -114,7 +114,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { destination, Constant { span: expr_span, - ty: this.hir.bool_ty(), user_ty: None, literal: this.hir.true_literal(), }, @@ -126,7 +125,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { destination, Constant { span: expr_span, - ty: this.hir.bool_ty(), user_ty: None, literal: this.hir.false_literal(), }, diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index d72b0addae9..94323b15b69 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -657,6 +657,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.visit_bindings(&subpattern.pattern, subpattern_user_ty, f); } } + PatternKind::Or { ref pats } => { + for pat in pats { + self.visit_bindings(&pat, pattern_user_ty.clone(), f); + } + } } } } diff --git a/src/librustc_mir/build/matches/simplify.rs b/src/librustc_mir/build/matches/simplify.rs index d9b748f71f0..8d049b53988 100644 --- a/src/librustc_mir/build/matches/simplify.rs +++ b/src/librustc_mir/build/matches/simplify.rs @@ -108,8 +108,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Err(match_pair) } - PatternKind::Range(PatternRange { lo, hi, ty, end }) => { - let (range, bias) = match ty.sty { + PatternKind::Range(PatternRange { lo, hi, end }) => { + let (range, bias) = match lo.ty.sty { ty::Char => { (Some(('\u{0000}' as u128, '\u{10FFFF}' as u128, Size::from_bits(32))), 0) } @@ -195,6 +195,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { candidate.match_pairs.push(MatchPair::new(place, subpattern)); Ok(()) } + + PatternKind::Or { .. } => { + Err(match_pair) + } } } } diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs index 1c93abd40de..ec85daccd47 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -63,7 +63,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } PatternKind::Range(range) => { - assert!(range.ty == match_pair.pattern.ty); + assert_eq!(range.lo.ty, match_pair.pattern.ty); + assert_eq!(range.hi.ty, match_pair.pattern.ty); Test { span: match_pair.pattern.span, kind: TestKind::Range(range), @@ -86,6 +87,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { PatternKind::AscribeUserType { .. } | PatternKind::Array { .. } | PatternKind::Wild | + PatternKind::Or { .. } | PatternKind::Binding { .. } | PatternKind::Leaf { .. } | PatternKind::Deref { .. } => { @@ -129,6 +131,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { PatternKind::Slice { .. } | PatternKind::Array { .. } | PatternKind::Wild | + PatternKind::Or { .. } | PatternKind::Binding { .. } | PatternKind::AscribeUserType { .. } | PatternKind::Leaf { .. } | @@ -270,8 +273,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ); } else { if let [success, fail] = *make_target_blocks(self) { + assert_eq!(value.ty, ty); + let expect = self.literal_operand(test.span, value); let val = Operand::Copy(place.clone()); - let expect = self.literal_operand(test.span, ty, value); self.compare(block, success, fail, source_info, BinOp::Eq, expect, val); } else { bug!("`TestKind::Eq` should have two target blocks"); @@ -279,13 +283,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - TestKind::Range(PatternRange { ref lo, ref hi, ty, ref end }) => { + TestKind::Range(PatternRange { ref lo, ref hi, ref end }) => { let lower_bound_success = self.cfg.start_new_block(); let target_blocks = make_target_blocks(self); // Test `val` by computing `lo <= val && val <= hi`, using primitive comparisons. - let lo = self.literal_operand(test.span, ty, lo); - let hi = self.literal_operand(test.span, ty, hi); + let lo = self.literal_operand(test.span, lo); + let hi = self.literal_operand(test.span, hi); let val = Operand::Copy(place.clone()); if let [success, fail] = *target_blocks { @@ -387,7 +391,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ) { use rustc::middle::lang_items::EqTraitLangItem; - let mut expect = self.literal_operand(source_info.span, value.ty, value); + let mut expect = self.literal_operand(source_info.span, value); let mut val = Operand::Copy(place.clone()); // If we're using `b"..."` as a pattern, we need to insert an @@ -440,7 +444,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }; let eq_def_id = self.hir.tcx().require_lang_item(EqTraitLangItem); - let (mty, method) = self.hir.trait_method(eq_def_id, sym::eq, deref_ty, &[deref_ty.into()]); + let method = self.hir.trait_method(eq_def_id, sym::eq, deref_ty, &[deref_ty.into()]); let bool_ty = self.hir.bool_ty(); let eq_result = self.temp(bool_ty, source_info.span); @@ -449,7 +453,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.cfg.terminate(block, source_info, TerminatorKind::Call { func: Operand::Constant(box Constant { span: source_info.span, - ty: mty, // FIXME(#54571): This constant comes from user input (a // constant in a pattern). Are there forms where users can add @@ -656,8 +659,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let tcx = self.hir.tcx(); - let lo = compare_const_vals(tcx, test.lo, pat.hi, self.hir.param_env, test.ty)?; - let hi = compare_const_vals(tcx, test.hi, pat.lo, self.hir.param_env, test.ty)?; + let test_ty = test.lo.ty; + let lo = compare_const_vals(tcx, test.lo, pat.hi, self.hir.param_env, test_ty)?; + let hi = compare_const_vals(tcx, test.hi, pat.lo, self.hir.param_env, test_ty)?; match (test.end, pat.end, lo, hi) { // pat < test @@ -774,8 +778,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let tcx = self.hir.tcx(); - let a = compare_const_vals(tcx, range.lo, value, self.hir.param_env, range.ty)?; - let b = compare_const_vals(tcx, value, range.hi, self.hir.param_env, range.ty)?; + let a = compare_const_vals(tcx, range.lo, value, self.hir.param_env, range.lo.ty)?; + let b = compare_const_vals(tcx, value, range.hi, self.hir.param_env, range.lo.ty)?; match (b, range.end) { (Less, _) | diff --git a/src/librustc_mir/build/misc.rs b/src/librustc_mir/build/misc.rs index 56025eeaaa9..d038310dd44 100644 --- a/src/librustc_mir/build/misc.rs +++ b/src/librustc_mir/build/misc.rs @@ -26,12 +26,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// without any user type annotation. pub fn literal_operand(&mut self, span: Span, - ty: Ty<'tcx>, literal: &'tcx ty::Const<'tcx>) -> Operand<'tcx> { let constant = box Constant { span, - ty, user_ty: None, literal, }; @@ -47,7 +45,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { pub fn zero_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> { let literal = ty::Const::from_bits(self.hir.tcx(), 0, ty::ParamEnv::empty().and(ty)); - self.literal_operand(span, ty, literal) + self.literal_operand(span, literal) } pub fn push_usize(&mut self, @@ -61,7 +59,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block, source_info, &temp, Constant { span: source_info.span, - ty: self.hir.usize_ty(), user_ty: None, literal: self.hir.usize_literal(value), }); diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 36d80d0cb57..76ee76a7456 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -11,9 +11,8 @@ use rustc::hir::def::DefKind; use rustc::hir::def_id::DefId; use rustc::mir::interpret::{ConstEvalErr, ErrorHandled, ScalarMaybeUndef}; use rustc::mir; -use rustc::ty::{self, TyCtxt}; +use rustc::ty::{self, Ty, TyCtxt, subst::Subst}; use rustc::ty::layout::{self, LayoutOf, VariantIdx}; -use rustc::ty::subst::Subst; use rustc::traits::Reveal; use rustc_data_structures::fx::FxHashMap; @@ -415,7 +414,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, _bin_op: mir::BinOp, _left: ImmTy<'tcx>, _right: ImmTy<'tcx>, - ) -> InterpResult<'tcx, (Scalar, bool)> { + ) -> InterpResult<'tcx, (Scalar, bool, Ty<'tcx>)> { Err( ConstEvalError::NeedsRfc("pointer arithmetic or comparison".to_string()).into(), ) @@ -540,6 +539,12 @@ pub fn error_to_const_error<'mir, 'tcx>( ConstEvalErr { error: error.kind, stacktrace, span: ecx.tcx.span } } +pub fn note_on_undefined_behavior_error() -> &'static str { + "The rules on what exactly is undefined behavior aren't clear, \ + so this check might be overzealous. Please open an issue on the rust compiler \ + repository if you believe it should not be considered undefined behavior" +} + fn validate_and_turn_into_const<'tcx>( tcx: TyCtxt<'tcx>, constant: RawConst<'tcx>, @@ -579,10 +584,7 @@ fn validate_and_turn_into_const<'tcx>( let err = error_to_const_error(&ecx, error); match err.struct_error(ecx.tcx, "it is undefined behavior to use this value") { Ok(mut diag) => { - diag.note("The rules on what exactly is undefined behavior aren't clear, \ - so this check might be overzealous. Please open an issue on the rust compiler \ - repository if you believe it should not be considered undefined behavior", - ); + diag.note(note_on_undefined_behavior_error()); diag.emit(); ErrorHandled::Reported } diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 1c6a743155e..a33d7207ed4 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -927,7 +927,7 @@ fn convert_path_expr<'a, 'tcx>( ExprKind::Literal { literal: cx.tcx.mk_const(ty::Const { val: ConstValue::Unevaluated(def_id, substs), - ty: cx.tcx.type_of(def_id), + ty: cx.tables().node_type(expr.hir_id), }), user_ty, } diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index 3d9349df5be..740dc2011ca 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -170,13 +170,13 @@ impl<'a, 'tcx> Cx<'a, 'tcx> { method_name: Symbol, self_ty: Ty<'tcx>, params: &[Kind<'tcx>]) - -> (Ty<'tcx>, &'tcx ty::Const<'tcx>) { + -> &'tcx ty::Const<'tcx> { let substs = self.tcx.mk_substs_trait(self_ty, params); for item in self.tcx.associated_items(trait_def_id) { if item.kind == ty::AssocKind::Method && item.ident.name == method_name { let method_ty = self.tcx.type_of(item.def_id); let method_ty = method_ty.subst(self.tcx, substs); - return (method_ty, ty::Const::zero_sized(self.tcx, method_ty)); + return ty::Const::zero_sized(self.tcx, method_ty); } } diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 8a3d904e775..222750e602d 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -609,7 +609,6 @@ impl<'tcx> Witness<'tcx> { ConstantRange(lo, hi, ty, end) => PatternKind::Range(PatternRange { lo: ty::Const::from_bits(cx.tcx, lo, ty::ParamEnv::empty().and(ty)), hi: ty::Const::from_bits(cx.tcx, hi, ty::ParamEnv::empty().and(ty)), - ty, end, }), _ => PatternKind::Wild, @@ -880,10 +879,10 @@ impl<'tcx> IntRange<'tcx> { let range = loop { match pat.kind { box PatternKind::Constant { value } => break ConstantValue(value), - box PatternKind::Range(PatternRange { lo, hi, ty, end }) => break ConstantRange( - lo.eval_bits(tcx, param_env, ty), - hi.eval_bits(tcx, param_env, ty), - ty, + box PatternKind::Range(PatternRange { lo, hi, end }) => break ConstantRange( + lo.eval_bits(tcx, param_env, lo.ty), + hi.eval_bits(tcx, param_env, hi.ty), + lo.ty, end, ), box PatternKind::AscribeUserType { ref subpattern, .. } => { @@ -1339,11 +1338,11 @@ fn pat_constructors<'tcx>(cx: &mut MatchCheckCtxt<'_, 'tcx>, Some(vec![Variant(adt_def.variants[variant_index].def_id)]) } PatternKind::Constant { value } => Some(vec![ConstantValue(value)]), - PatternKind::Range(PatternRange { lo, hi, ty, end }) => + PatternKind::Range(PatternRange { lo, hi, end }) => Some(vec![ConstantRange( - lo.eval_bits(cx.tcx, cx.param_env, ty), - hi.eval_bits(cx.tcx, cx.param_env, ty), - ty, + lo.eval_bits(cx.tcx, cx.param_env, lo.ty), + hi.eval_bits(cx.tcx, cx.param_env, hi.ty), + lo.ty, end, )]), PatternKind::Array { .. } => match pcx.ty.sty { @@ -1360,6 +1359,9 @@ fn pat_constructors<'tcx>(cx: &mut MatchCheckCtxt<'_, 'tcx>, Some(vec![Slice(pat_len)]) } } + PatternKind::Or { .. } => { + bug!("support for or-patterns has not been fully implemented yet."); + } } } @@ -1656,7 +1658,7 @@ fn constructor_covered_by_range<'tcx>( ) -> Result<bool, ErrorReported> { let (from, to, end, ty) = match pat.kind { box PatternKind::Constant { value } => (value, value, RangeEnd::Included, value.ty), - box PatternKind::Range(PatternRange { lo, hi, end, ty }) => (lo, hi, end, ty), + box PatternKind::Range(PatternRange { lo, hi, end }) => (lo, hi, end, lo.ty), _ => bug!("`constructor_covered_by_range` called with {:?}", pat), }; trace!("constructor_covered_by_range {:#?}, {:#?}, {:#?}, {}", ctor, from, to, ty); @@ -1885,6 +1887,10 @@ fn specialize<'p, 'a: 'p, 'tcx>( "unexpected ctor {:?} for slice pat", constructor) } } + + PatternKind::Or { .. } => { + bug!("support for or-patterns has not been fully implemented yet."); + } }; debug!("specialize({:#?}, {:#?}) = {:#?}", r[0], wild_patterns, head); diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 5ecfb84b632..6caccfddfa4 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -175,18 +175,35 @@ pub enum PatternKind<'tcx> { slice: Option<Pattern<'tcx>>, suffix: Vec<Pattern<'tcx>>, }, + + /// An or-pattern, e.g. `p | q`. + /// Invariant: `pats.len() >= 2`. + Or { + pats: Vec<Pattern<'tcx>>, + }, } #[derive(Copy, Clone, Debug, PartialEq)] pub struct PatternRange<'tcx> { pub lo: &'tcx ty::Const<'tcx>, pub hi: &'tcx ty::Const<'tcx>, - pub ty: Ty<'tcx>, pub end: RangeEnd, } impl<'tcx> fmt::Display for Pattern<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // Printing lists is a chore. + let mut first = true; + let mut start_or_continue = |s| { + if first { + first = false; + "" + } else { + s + } + }; + let mut start_or_comma = || start_or_continue(", "); + match *self.kind { PatternKind::Wild => write!(f, "_"), PatternKind::AscribeUserType { ref subpattern, .. } => @@ -225,9 +242,6 @@ impl<'tcx> fmt::Display for Pattern<'tcx> { } }; - let mut first = true; - let mut start_or_continue = || if first { first = false; "" } else { ", " }; - if let Some(variant) = variant { write!(f, "{}", variant.ident)?; @@ -242,12 +256,12 @@ impl<'tcx> fmt::Display for Pattern<'tcx> { continue; } let name = variant.fields[p.field.index()].ident; - write!(f, "{}{}: {}", start_or_continue(), name, p.pattern)?; + write!(f, "{}{}: {}", start_or_comma(), name, p.pattern)?; printed += 1; } if printed < variant.fields.len() { - write!(f, "{}..", start_or_continue())?; + write!(f, "{}..", start_or_comma())?; } return write!(f, " }}"); @@ -258,7 +272,7 @@ impl<'tcx> fmt::Display for Pattern<'tcx> { if num_fields != 0 || variant.is_none() { write!(f, "(")?; for i in 0..num_fields { - write!(f, "{}", start_or_continue())?; + write!(f, "{}", start_or_comma())?; // Common case: the field is where we expect it. if let Some(p) = subpatterns.get(i) { @@ -296,7 +310,7 @@ impl<'tcx> fmt::Display for Pattern<'tcx> { PatternKind::Constant { value } => { write!(f, "{}", value) } - PatternKind::Range(PatternRange { lo, hi, ty: _, end }) => { + PatternKind::Range(PatternRange { lo, hi, end }) => { write!(f, "{}", lo)?; match end { RangeEnd::Included => write!(f, "..=")?, @@ -306,14 +320,12 @@ impl<'tcx> fmt::Display for Pattern<'tcx> { } PatternKind::Slice { ref prefix, ref slice, ref suffix } | PatternKind::Array { ref prefix, ref slice, ref suffix } => { - let mut first = true; - let mut start_or_continue = || if first { first = false; "" } else { ", " }; write!(f, "[")?; for p in prefix { - write!(f, "{}{}", start_or_continue(), p)?; + write!(f, "{}{}", start_or_comma(), p)?; } if let Some(ref slice) = *slice { - write!(f, "{}", start_or_continue())?; + write!(f, "{}", start_or_comma())?; match *slice.kind { PatternKind::Wild => {} _ => write!(f, "{}", slice)? @@ -321,10 +333,16 @@ impl<'tcx> fmt::Display for Pattern<'tcx> { write!(f, "..")?; } for p in suffix { - write!(f, "{}{}", start_or_continue(), p)?; + write!(f, "{}{}", start_or_comma(), p)?; } write!(f, "]") } + PatternKind::Or { ref pats } => { + for pat in pats { + write!(f, "{}{}", start_or_continue(" | "), pat)?; + } + Ok(()) + } } } } @@ -442,6 +460,8 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { let mut kind = match (lo, hi) { (PatternKind::Constant { value: lo }, PatternKind::Constant { value: hi }) => { + assert_eq!(lo.ty, ty); + assert_eq!(hi.ty, ty); let cmp = compare_const_vals( self.tcx, lo, @@ -451,7 +471,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { ); match (end, cmp) { (RangeEnd::Excluded, Some(Ordering::Less)) => - PatternKind::Range(PatternRange { lo, hi, ty, end }), + PatternKind::Range(PatternRange { lo, hi, end }), (RangeEnd::Excluded, _) => { span_err!( self.tcx.sess, @@ -465,7 +485,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { PatternKind::Constant { value: lo } } (RangeEnd::Included, Some(Ordering::Less)) => { - PatternKind::Range(PatternRange { lo, hi, ty, end }) + PatternKind::Range(PatternRange { lo, hi, end }) } (RangeEnd::Included, _) => { let mut err = struct_span_err!( @@ -645,15 +665,21 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { fields.iter() .map(|field| { FieldPattern { - field: Field::new(self.tcx.field_index(field.node.hir_id, + field: Field::new(self.tcx.field_index(field.hir_id, self.tables)), - pattern: self.lower_pattern(&field.node.pat), + pattern: self.lower_pattern(&field.pat), } }) .collect(); self.lower_variant_or_leaf(res, pat.hir_id, pat.span, ty, subpatterns) } + + PatKind::Or(ref pats) => { + PatternKind::Or { + pats: pats.iter().map(|p| self.lower_pattern(p)).collect(), + } + } }; Pattern { @@ -1416,17 +1442,7 @@ impl<'tcx> PatternFoldable<'tcx> for PatternKind<'tcx> { } => PatternKind::Constant { value, }, - PatternKind::Range(PatternRange { - lo, - hi, - ty, - end, - }) => PatternKind::Range(PatternRange { - lo, - hi, - ty: ty.fold_with(folder), - end, - }), + PatternKind::Range(range) => PatternKind::Range(range), PatternKind::Slice { ref prefix, ref slice, @@ -1445,6 +1461,7 @@ impl<'tcx> PatternFoldable<'tcx> for PatternKind<'tcx> { slice: slice.fold_with(folder), suffix: suffix.fold_with(folder) }, + PatternKind::Or { ref pats } => PatternKind::Or { pats: pats.fold_with(folder) }, } } } diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index 26cfbfe53a3..210647ac1e9 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -1,4 +1,4 @@ -use rustc::ty::{self, Ty, TypeAndMut}; +use rustc::ty::{self, Ty, TypeAndMut, TypeFoldable}; use rustc::ty::layout::{self, TyLayout, Size}; use rustc::ty::adjustment::{PointerCast}; use syntax::ast::FloatTy; @@ -36,15 +36,15 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // The src operand does not matter, just its type match src.layout.ty.sty { ty::FnDef(def_id, substs) => { + // All reifications must be monomorphic, bail out otherwise. + if src.layout.ty.needs_subst() { + throw_inval!(TooGeneric); + } + if self.tcx.has_attr(def_id, sym::rustc_args_required_const) { bug!("reifying a fn ptr that requires const arguments"); } - let instance = ty::Instance::resolve( - *self.tcx, - self.param_env, - def_id, - substs, - ).ok_or_else(|| err_inval!(TooGeneric))?; + let instance = self.resolve(def_id, substs)?; let fn_ptr = self.memory.create_fn_alloc(FnVal::Instance(instance)); self.write_scalar(Scalar::Ptr(fn_ptr.into()), dest)?; } @@ -67,7 +67,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // The src operand does not matter, just its type match src.layout.ty.sty { ty::Closure(def_id, substs) => { - let substs = self.subst_and_normalize_erasing_regions(substs)?; + // All reifications must be monomorphic, bail out otherwise. + if src.layout.ty.needs_subst() { + throw_inval!(TooGeneric); + } + let instance = ty::Instance::resolve_closure( *self.tcx, def_id, diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 6f4227ed34c..6f48396cdd7 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -9,7 +9,7 @@ use rustc::mir; use rustc::ty::layout::{ self, Size, Align, HasDataLayout, LayoutOf, TyLayout }; -use rustc::ty::subst::{Subst, SubstsRef}; +use rustc::ty::subst::SubstsRef; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc::ty::query::TyCtxtAt; use rustc_data_structures::indexed_vec::IndexVec; @@ -291,41 +291,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ty.is_freeze(*self.tcx, self.param_env, DUMMY_SP) } - pub(super) fn subst_and_normalize_erasing_regions<T: TypeFoldable<'tcx>>( - &self, - substs: T, - ) -> InterpResult<'tcx, T> { - match self.stack.last() { - Some(frame) => Ok(self.tcx.subst_and_normalize_erasing_regions( - frame.instance.substs, - self.param_env, - &substs, - )), - None => if substs.needs_subst() { - throw_inval!(TooGeneric) - } else { - Ok(substs) - }, - } - } - - pub(super) fn resolve( - &self, - def_id: DefId, - substs: SubstsRef<'tcx> - ) -> InterpResult<'tcx, ty::Instance<'tcx>> { - trace!("resolve: {:?}, {:#?}", def_id, substs); - trace!("param_env: {:#?}", self.param_env); - let substs = self.subst_and_normalize_erasing_regions(substs)?; - trace!("substs: {:#?}", substs); - ty::Instance::resolve( - *self.tcx, - self.param_env, - def_id, - substs, - ).ok_or_else(|| err_inval!(TooGeneric).into()) - } - pub fn load_mir( &self, instance: ty::InstanceDef<'tcx>, @@ -349,34 +314,34 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } } - pub(super) fn monomorphize<T: TypeFoldable<'tcx> + Subst<'tcx>>( + /// Call this on things you got out of the MIR (so it is as generic as the current + /// stack frame), to bring it into the proper environment for this interpreter. + pub(super) fn subst_from_frame_and_normalize_erasing_regions<T: TypeFoldable<'tcx>>( &self, - t: T, - ) -> InterpResult<'tcx, T> { - match self.stack.last() { - Some(frame) => Ok(self.monomorphize_with_substs(t, frame.instance.substs)?), - None => if t.needs_subst() { - throw_inval!(TooGeneric) - } else { - Ok(t) - }, - } + value: T, + ) -> T { + self.tcx.subst_and_normalize_erasing_regions( + self.frame().instance.substs, + self.param_env, + &value, + ) } - fn monomorphize_with_substs<T: TypeFoldable<'tcx> + Subst<'tcx>>( + /// The `substs` are assumed to already be in our interpreter "universe" (param_env). + pub(super) fn resolve( &self, - t: T, + def_id: DefId, substs: SubstsRef<'tcx> - ) -> InterpResult<'tcx, T> { - // miri doesn't care about lifetimes, and will choke on some crazy ones - // let's simply get rid of them - let substituted = t.subst(*self.tcx, substs); - - if substituted.needs_subst() { - throw_inval!(TooGeneric) - } - - Ok(self.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), substituted)) + ) -> InterpResult<'tcx, ty::Instance<'tcx>> { + trace!("resolve: {:?}, {:#?}", def_id, substs); + trace!("param_env: {:#?}", self.param_env); + trace!("substs: {:#?}", substs); + ty::Instance::resolve( + *self.tcx, + self.param_env, + def_id, + substs, + ).ok_or_else(|| err_inval!(TooGeneric).into()) } pub fn layout_of_local( @@ -391,7 +356,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { None => { let layout = crate::interpret::operand::from_known_layout(layout, || { let local_ty = frame.body.local_decls[local].ty; - let local_ty = self.monomorphize_with_substs(local_ty, frame.instance.substs)?; + let local_ty = self.tcx.subst_and_normalize_erasing_regions( + frame.instance.substs, + self.param_env, + &local_ty, + ); self.layout_of(local_ty) })?; if let Some(state) = frame.locals.get(local) { diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs index 1074ab941a7..32ba70a81c9 100644 --- a/src/librustc_mir/interpret/intern.rs +++ b/src/librustc_mir/interpret/intern.rs @@ -296,11 +296,7 @@ pub fn intern_const_alloc_recursive( let err = crate::const_eval::error_to_const_error(&ecx, error); match err.struct_error(ecx.tcx, "it is undefined behavior to use this value") { Ok(mut diag) => { - diag.note("The rules on what exactly is undefined behavior aren't clear, \ - so this check might be overzealous. Please open an issue on the rust \ - compiler repository if you believe it should not be considered \ - undefined behavior", - ); + diag.note(crate::const_eval::note_on_undefined_behavior_error()); diag.emit(); } Err(ErrorHandled::TooGeneric) | diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index 89c5be137a4..4c86c53256e 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -110,18 +110,18 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { }; self.write_scalar(out_val, dest)?; } - | "overflowing_add" - | "overflowing_sub" - | "overflowing_mul" + | "wrapping_add" + | "wrapping_sub" + | "wrapping_mul" | "add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" => { let lhs = self.read_immediate(args[0])?; let rhs = self.read_immediate(args[1])?; let (bin_op, ignore_overflow) = match intrinsic_name { - "overflowing_add" => (BinOp::Add, true), - "overflowing_sub" => (BinOp::Sub, true), - "overflowing_mul" => (BinOp::Mul, true), + "wrapping_add" => (BinOp::Add, true), + "wrapping_sub" => (BinOp::Sub, true), + "wrapping_mul" => (BinOp::Mul, true), "add_with_overflow" => (BinOp::Add, false), "sub_with_overflow" => (BinOp::Sub, false), "mul_with_overflow" => (BinOp::Mul, false), @@ -137,7 +137,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let l = self.read_immediate(args[0])?; let r = self.read_immediate(args[1])?; let is_add = intrinsic_name == "saturating_add"; - let (val, overflowed) = self.binary_op(if is_add { + let (val, overflowed, _ty) = self.overflowing_binary_op(if is_add { BinOp::Add } else { BinOp::Sub @@ -184,7 +184,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { "unchecked_shr" => BinOp::Shr, _ => bug!("Already checked for int ops") }; - let (val, overflowed) = self.binary_op(bin_op, l, r)?; + let (val, overflowed, _ty) = self.overflowing_binary_op(bin_op, l, r)?; if overflowed { let layout = self.layout_of(substs.type_at(0))?; let r_val = r.to_scalar()?.to_bits(layout.size)?; diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index 33ffb1d320e..bb74a50156e 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -7,7 +7,7 @@ use std::hash::Hash; use rustc::hir::def_id::DefId; use rustc::mir; -use rustc::ty::{self, TyCtxt}; +use rustc::ty::{self, Ty, TyCtxt}; use super::{ Allocation, AllocId, InterpResult, Scalar, AllocationExtra, @@ -176,7 +176,7 @@ pub trait Machine<'mir, 'tcx>: Sized { bin_op: mir::BinOp, left: ImmTy<'tcx, Self::PointerTag>, right: ImmTy<'tcx, Self::PointerTag>, - ) -> InterpResult<'tcx, (Scalar<Self::PointerTag>, bool)>; + ) -> InterpResult<'tcx, (Scalar<Self::PointerTag>, bool, Ty<'tcx>)>; /// Heap allocations via the `box` keyword. fn box_alloc( diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index aef09df4537..87d36dabb04 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -297,7 +297,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { /// and `align`. On success, returns `None` for zero-sized accesses (where /// nothing else is left to do) and a `Pointer` to use for the actual access otherwise. /// Crucially, if the input is a `Pointer`, we will test it for liveness - /// *even of* the size is 0. + /// *even if* the size is 0. /// /// Everyone accessing memory based on a `Scalar` should use this method to get the /// `Pointer` they need. And even if you already have a `Pointer`, call this method @@ -368,7 +368,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // It is sufficient to check this for the end pointer. The addition // checks for overflow. let end_ptr = ptr.offset(size, self)?; - end_ptr.check_in_alloc(allocation_size, CheckInAllocMsg::MemoryAccessTest)?; + end_ptr.check_inbounds_alloc(allocation_size, CheckInAllocMsg::MemoryAccessTest)?; // Test align. Check this last; if both bounds and alignment are violated // we want the error to be about the bounds. if let Some(align) = align { @@ -400,7 +400,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { ) -> bool { let (size, _align) = self.get_size_and_align(ptr.alloc_id, AllocCheck::MaybeDead) .expect("alloc info with MaybeDead cannot fail"); - ptr.check_in_alloc(size, CheckInAllocMsg::NullPointerTest).is_err() + ptr.check_inbounds_alloc(size, CheckInAllocMsg::NullPointerTest).is_err() } } diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index f778eb1734c..7a545e8ad6f 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -108,7 +108,7 @@ impl<'tcx, Tag> Immediate<Tag> { // as input for binary and cast operations. #[derive(Copy, Clone, Debug)] pub struct ImmTy<'tcx, Tag=()> { - pub imm: Immediate<Tag>, + pub(crate) imm: Immediate<Tag>, pub layout: TyLayout<'tcx>, } @@ -155,7 +155,7 @@ impl<Tag> Operand<Tag> { #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct OpTy<'tcx, Tag=()> { - op: Operand<Tag>, + op: Operand<Tag>, // Keep this private, it helps enforce invariants pub layout: TyLayout<'tcx>, } @@ -187,14 +187,23 @@ impl<'tcx, Tag> From<ImmTy<'tcx, Tag>> for OpTy<'tcx, Tag> { } } -impl<'tcx, Tag: Copy> ImmTy<'tcx, Tag> -{ +impl<'tcx, Tag: Copy> ImmTy<'tcx, Tag> { #[inline] pub fn from_scalar(val: Scalar<Tag>, layout: TyLayout<'tcx>) -> Self { ImmTy { imm: val.into(), layout } } #[inline] + pub fn from_uint(i: impl Into<u128>, layout: TyLayout<'tcx>) -> Self { + Self::from_scalar(Scalar::from_uint(i, layout.size), layout) + } + + #[inline] + pub fn from_int(i: impl Into<i128>, layout: TyLayout<'tcx>) -> Self { + Self::from_scalar(Scalar::from_int(i, layout.size), layout) + } + + #[inline] pub fn to_bits(self) -> InterpResult<'tcx, u128> { self.to_scalar()?.to_bits(self.layout.size) } @@ -246,7 +255,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { return Ok(None); } - let ptr = match self.check_mplace_access(mplace, None)? { + let ptr = match self.check_mplace_access(mplace, None) + .expect("places should be checked on creation") + { Some(ptr) => ptr, None => return Ok(Some(ImmTy { // zero-sized type imm: Scalar::zst().into(), @@ -511,7 +522,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Move(ref place) => self.eval_place_to_op(place, layout)?, - Constant(ref constant) => self.eval_const_to_op(constant.literal, layout)?, + Constant(ref constant) => { + let val = self.subst_from_frame_and_normalize_erasing_regions(constant.literal); + self.eval_const_to_op(val, layout)? + } }; trace!("{:?}: {:?}", mir_op, *op); Ok(op) @@ -529,6 +543,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Used when the miri-engine runs into a constant and for extracting information from constants // in patterns via the `const_eval` module + /// The `val` and `layout` are assumed to already be in our interpreter + /// "universe" (param_env). crate fn eval_const_to_op( &self, val: &'tcx ty::Const<'tcx>, @@ -541,7 +557,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Early-return cases. match val.val { ConstValue::Param(_) => - // FIXME(oli-obk): try to monomorphize throw_inval!(TooGeneric), ConstValue::Unevaluated(def_id, substs) => { let instance = self.resolve(def_id, substs)?; @@ -554,7 +569,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } // Other cases need layout. let layout = from_known_layout(layout, || { - self.layout_of(self.monomorphize(val.ty)?) + self.layout_of(val.ty) })?; let op = match val.val { ConstValue::ByRef { alloc, offset } => { diff --git a/src/librustc_mir/interpret/operator.rs b/src/librustc_mir/interpret/operator.rs index e638ebcc342..470cc9346ee 100644 --- a/src/librustc_mir/interpret/operator.rs +++ b/src/librustc_mir/interpret/operator.rs @@ -1,5 +1,5 @@ use rustc::mir; -use rustc::ty::{self, layout::TyLayout}; +use rustc::ty::{self, Ty, layout::{TyLayout, LayoutOf}}; use syntax::ast::FloatTy; use rustc_apfloat::Float; use rustc::mir::interpret::{InterpResult, Scalar}; @@ -17,7 +17,12 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { right: ImmTy<'tcx, M::PointerTag>, dest: PlaceTy<'tcx, M::PointerTag>, ) -> InterpResult<'tcx> { - let (val, overflowed) = self.binary_op(op, left, right)?; + let (val, overflowed, ty) = self.overflowing_binary_op(op, left, right)?; + debug_assert_eq!( + self.tcx.intern_tup(&[ty, self.tcx.types.bool]), + dest.layout.ty, + "type mismatch for result of {:?}", op, + ); let val = Immediate::ScalarPair(val.into(), Scalar::from_bool(overflowed).into()); self.write_immediate(val, dest) } @@ -31,7 +36,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { right: ImmTy<'tcx, M::PointerTag>, dest: PlaceTy<'tcx, M::PointerTag>, ) -> InterpResult<'tcx> { - let (val, _overflowed) = self.binary_op(op, left, right)?; + let (val, _overflowed, ty) = self.overflowing_binary_op(op, left, right)?; + assert_eq!(ty, dest.layout.ty, "type mismatch for result of {:?}", op); self.write_scalar(val, dest) } } @@ -42,7 +48,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { bin_op: mir::BinOp, l: char, r: char, - ) -> (Scalar<M::PointerTag>, bool) { + ) -> (Scalar<M::PointerTag>, bool, Ty<'tcx>) { use rustc::mir::BinOp::*; let res = match bin_op { @@ -54,7 +60,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Ge => l >= r, _ => bug!("Invalid operation on char: {:?}", bin_op), }; - return (Scalar::from_bool(res), false); + return (Scalar::from_bool(res), false, self.tcx.types.bool); } fn binary_bool_op( @@ -62,7 +68,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { bin_op: mir::BinOp, l: bool, r: bool, - ) -> (Scalar<M::PointerTag>, bool) { + ) -> (Scalar<M::PointerTag>, bool, Ty<'tcx>) { use rustc::mir::BinOp::*; let res = match bin_op { @@ -77,32 +83,33 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { BitXor => l ^ r, _ => bug!("Invalid operation on bool: {:?}", bin_op), }; - return (Scalar::from_bool(res), false); + return (Scalar::from_bool(res), false, self.tcx.types.bool); } fn binary_float_op<F: Float + Into<Scalar<M::PointerTag>>>( &self, bin_op: mir::BinOp, + ty: Ty<'tcx>, l: F, r: F, - ) -> (Scalar<M::PointerTag>, bool) { + ) -> (Scalar<M::PointerTag>, bool, Ty<'tcx>) { use rustc::mir::BinOp::*; - let val = match bin_op { - Eq => Scalar::from_bool(l == r), - Ne => Scalar::from_bool(l != r), - Lt => Scalar::from_bool(l < r), - Le => Scalar::from_bool(l <= r), - Gt => Scalar::from_bool(l > r), - Ge => Scalar::from_bool(l >= r), - Add => (l + r).value.into(), - Sub => (l - r).value.into(), - Mul => (l * r).value.into(), - Div => (l / r).value.into(), - Rem => (l % r).value.into(), + let (val, ty) = match bin_op { + Eq => (Scalar::from_bool(l == r), self.tcx.types.bool), + Ne => (Scalar::from_bool(l != r), self.tcx.types.bool), + Lt => (Scalar::from_bool(l < r), self.tcx.types.bool), + Le => (Scalar::from_bool(l <= r), self.tcx.types.bool), + Gt => (Scalar::from_bool(l > r), self.tcx.types.bool), + Ge => (Scalar::from_bool(l >= r), self.tcx.types.bool), + Add => ((l + r).value.into(), ty), + Sub => ((l - r).value.into(), ty), + Mul => ((l * r).value.into(), ty), + Div => ((l / r).value.into(), ty), + Rem => ((l % r).value.into(), ty), _ => bug!("invalid float op: `{:?}`", bin_op), }; - return (val, false); + return (val, false, ty); } fn binary_int_op( @@ -113,7 +120,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { left_layout: TyLayout<'tcx>, r: u128, right_layout: TyLayout<'tcx>, - ) -> InterpResult<'tcx, (Scalar<M::PointerTag>, bool)> { + ) -> InterpResult<'tcx, (Scalar<M::PointerTag>, bool, Ty<'tcx>)> { use rustc::mir::BinOp::*; // Shift ops can have an RHS with a different numeric type. @@ -142,7 +149,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } }; let truncated = self.truncate(result, left_layout); - return Ok((Scalar::from_uint(truncated, size), oflo)); + return Ok((Scalar::from_uint(truncated, size), oflo, left_layout.ty)); } // For the remaining ops, the types must be the same on both sides @@ -167,7 +174,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { if let Some(op) = op { let l = self.sign_extend(l, left_layout) as i128; let r = self.sign_extend(r, right_layout) as i128; - return Ok((Scalar::from_bool(op(&l, &r)), false)); + return Ok((Scalar::from_bool(op(&l, &r)), false, self.tcx.types.bool)); } let op: Option<fn(i128, i128) -> (i128, bool)> = match bin_op { Div if r == 0 => throw_panic!(DivisionByZero), @@ -187,7 +194,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Rem | Div => { // int_min / -1 if r == -1 && l == (1 << (size.bits() - 1)) { - return Ok((Scalar::from_uint(l, size), true)); + return Ok((Scalar::from_uint(l, size), true, left_layout.ty)); } }, _ => {}, @@ -202,25 +209,24 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // this may be out-of-bounds for the result type, so we have to truncate ourselves let result = result as u128; let truncated = self.truncate(result, left_layout); - return Ok((Scalar::from_uint(truncated, size), oflo)); + return Ok((Scalar::from_uint(truncated, size), oflo, left_layout.ty)); } } let size = left_layout.size; - // only ints left - let val = match bin_op { - Eq => Scalar::from_bool(l == r), - Ne => Scalar::from_bool(l != r), + let (val, ty) = match bin_op { + Eq => (Scalar::from_bool(l == r), self.tcx.types.bool), + Ne => (Scalar::from_bool(l != r), self.tcx.types.bool), - Lt => Scalar::from_bool(l < r), - Le => Scalar::from_bool(l <= r), - Gt => Scalar::from_bool(l > r), - Ge => Scalar::from_bool(l >= r), + Lt => (Scalar::from_bool(l < r), self.tcx.types.bool), + Le => (Scalar::from_bool(l <= r), self.tcx.types.bool), + Gt => (Scalar::from_bool(l > r), self.tcx.types.bool), + Ge => (Scalar::from_bool(l >= r), self.tcx.types.bool), - BitOr => Scalar::from_uint(l | r, size), - BitAnd => Scalar::from_uint(l & r, size), - BitXor => Scalar::from_uint(l ^ r, size), + BitOr => (Scalar::from_uint(l | r, size), left_layout.ty), + BitAnd => (Scalar::from_uint(l & r, size), left_layout.ty), + BitXor => (Scalar::from_uint(l ^ r, size), left_layout.ty), Add | Sub | Mul | Rem | Div => { debug_assert!(!left_layout.abi.is_signed()); @@ -236,7 +242,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { }; let (result, oflo) = op(l, r); let truncated = self.truncate(result, left_layout); - return Ok((Scalar::from_uint(truncated, size), oflo || truncated != result)); + return Ok(( + Scalar::from_uint(truncated, size), + oflo || truncated != result, + left_layout.ty, + )); } _ => { @@ -250,17 +260,17 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } }; - Ok((val, false)) + Ok((val, false, ty)) } - /// Returns the result of the specified operation and whether it overflowed. - #[inline] - pub fn binary_op( + /// Returns the result of the specified operation, whether it overflowed, and + /// the result type. + pub fn overflowing_binary_op( &self, bin_op: mir::BinOp, left: ImmTy<'tcx, M::PointerTag>, right: ImmTy<'tcx, M::PointerTag>, - ) -> InterpResult<'tcx, (Scalar<M::PointerTag>, bool)> { + ) -> InterpResult<'tcx, (Scalar<M::PointerTag>, bool, Ty<'tcx>)> { trace!("Running binary op {:?}: {:?} ({:?}), {:?} ({:?})", bin_op, *left, left.layout.ty, *right, right.layout.ty); @@ -279,11 +289,14 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } ty::Float(fty) => { assert_eq!(left.layout.ty, right.layout.ty); + let ty = left.layout.ty; let left = left.to_scalar()?; let right = right.to_scalar()?; Ok(match fty { - FloatTy::F32 => self.binary_float_op(bin_op, left.to_f32()?, right.to_f32()?), - FloatTy::F64 => self.binary_float_op(bin_op, left.to_f64()?, right.to_f64()?), + FloatTy::F32 => + self.binary_float_op(bin_op, ty, left.to_f32()?, right.to_f32()?), + FloatTy::F64 => + self.binary_float_op(bin_op, ty, left.to_f64()?, right.to_f64()?), }) } _ if left.layout.ty.is_integral() => { @@ -312,11 +325,23 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } } + /// Typed version of `checked_binary_op`, returning an `ImmTy`. Also ignores overflows. + #[inline] + pub fn binary_op( + &self, + bin_op: mir::BinOp, + left: ImmTy<'tcx, M::PointerTag>, + right: ImmTy<'tcx, M::PointerTag>, + ) -> InterpResult<'tcx, ImmTy<'tcx, M::PointerTag>> { + let (val, _overflow, ty) = self.overflowing_binary_op(bin_op, left, right)?; + Ok(ImmTy::from_scalar(val, self.layout_of(ty)?)) + } + pub fn unary_op( &self, un_op: mir::UnOp, val: ImmTy<'tcx, M::PointerTag>, - ) -> InterpResult<'tcx, Scalar<M::PointerTag>> { + ) -> InterpResult<'tcx, ImmTy<'tcx, M::PointerTag>> { use rustc::mir::UnOp::*; let layout = val.layout; @@ -330,7 +355,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Not => !val, _ => bug!("Invalid bool op {:?}", un_op) }; - Ok(Scalar::from_bool(res)) + Ok(ImmTy::from_scalar(Scalar::from_bool(res), self.layout_of(self.tcx.types.bool)?)) } ty::Float(fty) => { let res = match (un_op, fty) { @@ -338,7 +363,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { (Neg, FloatTy::F64) => Scalar::from_f64(-val.to_f64()?), _ => bug!("Invalid float op {:?}", un_op) }; - Ok(res) + Ok(ImmTy::from_scalar(res, layout)) } _ => { assert!(layout.ty.is_integral()); @@ -351,7 +376,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } }; // res needs tuncating - Ok(Scalar::from_uint(self.truncate(res, layout), layout.size)) + Ok(ImmTy::from_uint(self.truncate(res, layout), layout)) } } } diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index f66c4adf763..85f9cbd3758 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -45,7 +45,7 @@ pub enum Place<Tag=(), Id=AllocId> { #[derive(Copy, Clone, Debug)] pub struct PlaceTy<'tcx, Tag=()> { - place: Place<Tag>, + place: Place<Tag>, // Keep this private, it helps enforce invariants pub layout: TyLayout<'tcx>, } @@ -277,6 +277,10 @@ where { /// Take a value, which represents a (thin or fat) reference, and make it a place. /// Alignment is just based on the type. This is the inverse of `MemPlace::to_ref()`. + /// + /// Only call this if you are sure the place is "valid" (aligned and inbounds), or do not + /// want to ever use the place for memory access! + /// Generally prefer `deref_operand`. pub fn ref_to_mplace( &self, val: ImmTy<'tcx, M::PointerTag>, @@ -304,7 +308,8 @@ where ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { let val = self.read_immediate(src)?; trace!("deref to {} on {:?}", val.layout.ty, *val); - self.ref_to_mplace(val) + let place = self.ref_to_mplace(val)?; + self.mplace_access_checked(place) } /// Check if the given place is good for memory access with the given @@ -327,6 +332,23 @@ where self.memory.check_ptr_access(place.ptr, size, place.align) } + /// Return the "access-checked" version of this `MPlace`, where for non-ZST + /// this is definitely a `Pointer`. + pub fn mplace_access_checked( + &self, + mut place: MPlaceTy<'tcx, M::PointerTag>, + ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { + let (size, align) = self.size_and_align_of_mplace(place)? + .unwrap_or((place.layout.size, place.layout.align.abi)); + assert!(place.mplace.align <= align, "dynamic alignment less strict than static one?"); + place.mplace.align = align; // maximally strict checking + // When dereferencing a pointer, it must be non-NULL, aligned, and live. + if let Some(ptr) = self.check_mplace_access(place, Some(size))? { + place.mplace.ptr = ptr.into(); + } + Ok(place) + } + /// Force `place.ptr` to a `Pointer`. /// Can be helpful to avoid lots of `force_ptr` calls later, if this place is used a lot. pub fn force_mplace_ptr( @@ -618,8 +640,11 @@ where // their layout on return. PlaceTy { place: *return_place, - layout: self - .layout_of(self.monomorphize(self.frame().body.return_ty())?)?, + layout: self.layout_of( + self.subst_from_frame_and_normalize_erasing_regions( + self.frame().body.return_ty() + ) + )?, } } None => throw_unsup!(InvalidNullPointerUsage), @@ -750,7 +775,9 @@ where // to handle padding properly, which is only correct if we never look at this data with the // wrong type. - let ptr = match self.check_mplace_access(dest, None)? { + let ptr = match self.check_mplace_access(dest, None) + .expect("places should be checked on creation") + { Some(ptr) => ptr, None => return Ok(()), // zero-sized access }; @@ -853,8 +880,10 @@ where }); assert_eq!(src.meta, dest.meta, "Can only copy between equally-sized instances"); - let src = self.check_mplace_access(src, Some(size))?; - let dest = self.check_mplace_access(dest, Some(size))?; + let src = self.check_mplace_access(src, Some(size)) + .expect("places should be checked on creation"); + let dest = self.check_mplace_access(dest, Some(size)) + .expect("places should be checked on creation"); let (src_ptr, dest_ptr) = match (src, dest) { (Some(src_ptr), Some(dest_ptr)) => (src_ptr, dest_ptr), (None, None) => return Ok(()), // zero-sized copy diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs index d152e2b50fa..ca4da451a1f 100644 --- a/src/librustc_mir/interpret/step.rs +++ b/src/librustc_mir/interpret/step.rs @@ -177,7 +177,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // The operand always has the same type as the result. let val = self.read_immediate(self.eval_operand(operand, Some(dest.layout))?)?; let val = self.unary_op(un_op, val)?; - self.write_scalar(val, dest)?; + assert_eq!(val.layout, dest.layout, "layout mismatch for result of {:?}", un_op); + self.write_immediate(*val, dest)?; } Aggregate(ref kind, ref operands) => { @@ -240,8 +241,12 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Ref(_, _, ref place) => { let src = self.eval_place(place)?; - let val = self.force_allocation(src)?; - self.write_immediate(val.to_ref(), dest)?; + let place = self.force_allocation(src)?; + if place.layout.size.bytes() > 0 { + // definitely not a ZST + assert!(place.ptr.is_ptr(), "non-ZST places should be normalized to `Pointer`"); + } + self.write_immediate(place.to_ref(), dest)?; } NullaryOp(mir::NullOp::Box, _) => { @@ -249,7 +254,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } NullaryOp(mir::NullOp::SizeOf, ty) => { - let ty = self.monomorphize(ty)?; + let ty = self.subst_from_frame_and_normalize_erasing_regions(ty); let layout = self.layout_of(ty)?; assert!(!layout.is_unsized(), "SizeOf nullary MIR operator called for unsized type"); diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs index 1d6b48e9da4..5de297923ce 100644 --- a/src/librustc_mir/interpret/terminator.rs +++ b/src/librustc_mir/interpret/terminator.rs @@ -7,7 +7,7 @@ use syntax::source_map::Span; use rustc_target::spec::abi::Abi; use super::{ - InterpResult, PointerArithmetic, Scalar, + InterpResult, PointerArithmetic, InterpCx, Machine, OpTy, ImmTy, PlaceTy, MPlaceTy, StackPopCleanup, FnVal, }; @@ -50,11 +50,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { for (index, &const_int) in values.iter().enumerate() { // Compare using binary_op, to also support pointer values - let const_int = Scalar::from_uint(const_int, discr.layout.size); - let (res, _) = self.binary_op(mir::BinOp::Eq, + let res = self.overflowing_binary_op(mir::BinOp::Eq, discr, - ImmTy::from_scalar(const_int, discr.layout), - )?; + ImmTy::from_uint(const_int, discr.layout), + )?.0; if res.to_bool()? { target_block = targets[index]; break; diff --git a/src/librustc_mir/interpret/traits.rs b/src/librustc_mir/interpret/traits.rs index e55b0d0fb1f..a2fc75739ff 100644 --- a/src/librustc_mir/interpret/traits.rs +++ b/src/librustc_mir/interpret/traits.rs @@ -1,4 +1,4 @@ -use rustc::ty::{self, Ty, Instance}; +use rustc::ty::{self, Ty, Instance, TypeFoldable}; use rustc::ty::layout::{Size, Align, LayoutOf}; use rustc::mir::interpret::{Scalar, Pointer, InterpResult, PointerArithmetic,}; @@ -20,6 +20,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let (ty, poly_trait_ref) = self.tcx.erase_regions(&(ty, poly_trait_ref)); + // All vtables must be monomorphic, bail out otherwise. + if ty.needs_subst() || poly_trait_ref.needs_subst() { + throw_inval!(TooGeneric); + } + if let Some(&vtable) = self.vtables.get(&(ty, poly_trait_ref)) { // This means we guarantee that there are no duplicate vtables, we will // always use the same vtable for the same (Type, Trait) combination. @@ -77,7 +82,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { for (i, method) in methods.iter().enumerate() { if let Some((def_id, substs)) = *method { // resolve for vtable: insert shims where needed - let substs = self.subst_and_normalize_erasing_regions(substs)?; let instance = ty::Instance::resolve_for_vtable( *self.tcx, self.param_env, diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 33447eba749..3e02f6c3725 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -445,7 +445,6 @@ impl CloneShimBuilder<'tcx> { let func_ty = tcx.mk_fn_def(self.def_id, substs); let func = Operand::Constant(box Constant { span: self.span, - ty: func_ty, user_ty: None, literal: ty::Const::zero_sized(tcx, func_ty), }); @@ -505,7 +504,6 @@ impl CloneShimBuilder<'tcx> { fn make_usize(&self, value: u64) -> Box<Constant<'tcx>> { box Constant { span: self.span, - ty: self.tcx.types.usize, user_ty: None, literal: ty::Const::from_usize(self.tcx, value), } @@ -710,7 +708,7 @@ fn build_call_shim<'tcx>( Adjustment::DerefMove => { // fn(Self, ...) -> fn(*mut Self, ...) let arg_ty = local_decls[rcvr_arg].ty; - assert!(arg_ty.is_self()); + debug_assert!(tcx.generics_of(def_id).has_self && arg_ty == tcx.types.self_param); local_decls[rcvr_arg].ty = tcx.mk_mut_ptr(arg_ty); Operand::Move(rcvr_l.deref()) @@ -745,7 +743,6 @@ fn build_call_shim<'tcx>( let ty = tcx.type_of(def_id); (Operand::Constant(box Constant { span, - ty, user_ty: None, literal: ty::Const::zero_sized(tcx, ty), }), diff --git a/src/librustc_mir/transform/add_retag.rs b/src/librustc_mir/transform/add_retag.rs index d573423906c..524a19e3434 100644 --- a/src/librustc_mir/transform/add_retag.rs +++ b/src/librustc_mir/transform/add_retag.rs @@ -42,9 +42,8 @@ fn is_stable( } } -/// Determine whether this type may have a reference in it, recursing below compound types but -/// not below references. -fn may_have_reference<'tcx>(ty: Ty<'tcx>, tcx: TyCtxt<'tcx>) -> bool { +/// Determine whether this type may be a reference (or box), and thus needs retagging. +fn may_be_reference<'tcx>(ty: Ty<'tcx>) -> bool { match ty.sty { // Primitive types that are not references ty::Bool | ty::Char | @@ -55,15 +54,12 @@ fn may_have_reference<'tcx>(ty: Ty<'tcx>, tcx: TyCtxt<'tcx>) -> bool { // References ty::Ref(..) => true, ty::Adt(..) if ty.is_box() => true, - // Compound types - ty::Array(ty, ..) | ty::Slice(ty) => - may_have_reference(ty, tcx), - ty::Tuple(tys) => - tys.iter().any(|ty| may_have_reference(ty.expect_ty(), tcx)), - ty::Adt(adt, substs) => - adt.variants.iter().any(|v| v.fields.iter().any(|f| - may_have_reference(f.ty(tcx, substs), tcx) - )), + // Compound types are not references + ty::Array(..) | + ty::Slice(..) | + ty::Tuple(..) | + ty::Adt(..) => + false, // Conservative fallback _ => true, } @@ -80,7 +76,7 @@ impl MirPass for AddRetag { // FIXME: Instead of giving up for unstable places, we should introduce // a temporary and retag on that. is_stable(place.as_ref()) - && may_have_reference(place.ty(&*local_decls, tcx).ty, tcx) + && may_be_reference(place.ty(&*local_decls, tcx).ty) }; // PART 1 diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 38d26d0ba50..98d8ca58ee1 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -19,7 +19,7 @@ use syntax_pos::{Span, DUMMY_SP}; use rustc::ty::subst::InternalSubsts; use rustc_data_structures::indexed_vec::IndexVec; use rustc::ty::layout::{ - LayoutOf, TyLayout, LayoutError, HasTyCtxt, TargetDataLayout, HasDataLayout, Size, + LayoutOf, TyLayout, LayoutError, HasTyCtxt, TargetDataLayout, HasDataLayout, }; use crate::interpret::{ @@ -396,17 +396,10 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { if let ty::Slice(_) = mplace.layout.ty.sty { let len = mplace.meta.unwrap().to_usize(&self.ecx).unwrap(); - Some(ImmTy { - imm: Immediate::Scalar( - Scalar::from_uint( - len, - Size::from_bits( - self.tcx.sess.target.usize_ty.bit_width().unwrap() as u64 - ) - ).into(), - ), - layout: self.tcx.layout_of(self.param_env.and(self.tcx.types.usize)).ok()?, - }.into()) + Some(ImmTy::from_uint( + len, + self.tcx.layout_of(self.param_env.and(self.tcx.types.usize)).ok()?, + ).into()) } else { trace!("not slice: {:?}", mplace.layout.ty.sty); None @@ -414,12 +407,10 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { }, Rvalue::NullaryOp(NullOp::SizeOf, ty) => { type_size_of(self.tcx, self.param_env, ty).and_then(|n| Some( - ImmTy { - imm: Immediate::Scalar( - Scalar::from_uint(n, self.tcx.data_layout.pointer_size).into() - ), - layout: self.tcx.layout_of(self.param_env.and(self.tcx.types.usize)).ok()?, - }.into() + ImmTy::from_uint( + n, + self.tcx.layout_of(self.param_env.and(self.tcx.types.usize)).ok()?, + ).into() )) } Rvalue::UnaryOp(op, ref arg) => { @@ -452,11 +443,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { // Now run the actual operation. this.ecx.unary_op(op, prim) })?; - let res = ImmTy { - imm: Immediate::Scalar(val.into()), - layout: place_layout, - }; - Some(res.into()) + Some(val.into()) } Rvalue::CheckedBinaryOp(op, ref left, ref right) | Rvalue::BinaryOp(op, ref left, ref right) => { @@ -510,8 +497,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { this.ecx.read_immediate(left) })?; trace!("const evaluating {:?} for {:?} and {:?}", op, left, right); - let (val, overflow) = self.use_ecx(source_info, |this| { - this.ecx.binary_op(op, l, r) + let (val, overflow, _ty) = self.use_ecx(source_info, |this| { + this.ecx.overflowing_binary_op(op, l, r) })?; let val = if let Rvalue::CheckedBinaryOp(..) = *rvalue { Immediate::ScalarPair( @@ -539,7 +526,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { Operand::Constant(Box::new( Constant { span, - ty, user_ty: None, literal: self.tcx.mk_const(*ty::Const::from_scalar( self.tcx, diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs index 0a021d9b8fa..4480d1e0a05 100644 --- a/src/librustc_mir/transform/elaborate_drops.rs +++ b/src/librustc_mir/transform/elaborate_drops.rs @@ -527,7 +527,6 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { fn constant_bool(&self, span: Span, val: bool) -> Rvalue<'tcx> { Rvalue::Use(Operand::Constant(Box::new(Constant { span, - ty: self.tcx.types.bool, user_ty: None, literal: ty::Const::from_bool(self.tcx, val), }))) diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 94bb70e10aa..f6941880240 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -975,7 +975,6 @@ fn insert_panic_block<'tcx>( let term = TerminatorKind::Assert { cond: Operand::Constant(box Constant { span: body.span, - ty: tcx.types.bool, user_ty: None, literal: ty::Const::from_bool(tcx, false), }), diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 40cb1fbdc57..bc7bd39be48 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -328,7 +328,7 @@ impl Inliner<'tcx> { } TerminatorKind::Call {func: Operand::Constant(ref f), .. } => { - if let ty::FnDef(def_id, _) = f.ty.sty { + if let ty::FnDef(def_id, _) = f.literal.ty.sty { // Don't give intrinsics the extra penalty for calls let f = tcx.fn_sig(def_id); if f.abi() == Abi::RustIntrinsic || f.abi() == Abi::PlatformIntrinsic { diff --git a/src/librustc_mir/transform/instcombine.rs b/src/librustc_mir/transform/instcombine.rs index 55429265036..b2d063a1f4e 100644 --- a/src/librustc_mir/transform/instcombine.rs +++ b/src/librustc_mir/transform/instcombine.rs @@ -97,8 +97,7 @@ impl Visitor<'tcx> for OptimizationFinder<'b, 'tcx> { let place_ty = place.ty(&self.body.local_decls, self.tcx).ty; if let ty::Array(_, len) = place_ty.sty { let span = self.body.source_info(location).span; - let ty = self.tcx.types.usize; - let constant = Constant { span, ty, literal: len, user_ty: None }; + let constant = Constant { span, literal: len, user_ty: None }; self.optimizations.arrays_lengths.insert(location, constant); } } diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index dcfc80968f3..649cccc36c3 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -249,7 +249,7 @@ trait Qualif { if let ConstValue::Unevaluated(def_id, _) = constant.literal.val { // Don't peek inside trait associated constants. if cx.tcx.trait_of_item(def_id).is_some() { - Self::in_any_value_of_ty(cx, constant.ty).unwrap_or(false) + Self::in_any_value_of_ty(cx, constant.literal.ty).unwrap_or(false) } else { let (bits, _) = cx.tcx.at(constant.span).mir_const_qualif(def_id); @@ -258,7 +258,7 @@ trait Qualif { // Just in case the type is more specific than // the definition, e.g., impl associated const // with type parameters, take it into account. - qualif && Self::mask_for_ty(cx, constant.ty) + qualif && Self::mask_for_ty(cx, constant.literal.ty) } } else { false @@ -537,9 +537,9 @@ impl Qualif for IsNotPromotable { | "cttz_nonzero" | "ctlz" | "ctlz_nonzero" - | "overflowing_add" - | "overflowing_sub" - | "overflowing_mul" + | "wrapping_add" + | "wrapping_sub" + | "wrapping_mul" | "unchecked_shl" | "unchecked_shr" | "rotate_left" diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs index b84bc31ec2a..334d0cee9fb 100644 --- a/src/librustc_mir/transform/qualify_min_const_fn.rs +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -379,9 +379,9 @@ fn is_intrinsic_whitelisted(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool { | "add_with_overflow" // ~> .overflowing_add | "sub_with_overflow" // ~> .overflowing_sub | "mul_with_overflow" // ~> .overflowing_mul - | "overflowing_add" // ~> .wrapping_add - | "overflowing_sub" // ~> .wrapping_sub - | "overflowing_mul" // ~> .wrapping_mul + | "wrapping_add" // ~> .wrapping_add + | "wrapping_sub" // ~> .wrapping_sub + | "wrapping_mul" // ~> .wrapping_mul | "saturating_add" // ~> .saturating_add | "saturating_sub" // ~> .saturating_sub | "unchecked_shl" // ~> .wrapping_shl diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs index 7fe8480c819..598de3a77e6 100644 --- a/src/librustc_mir/transform/rustc_peek.rs +++ b/src/librustc_mir/transform/rustc_peek.rs @@ -224,7 +224,7 @@ fn is_rustc_peek<'a, 'tcx>( if let Some(mir::Terminator { ref kind, source_info, .. }) = *terminator { if let mir::TerminatorKind::Call { func: ref oper, ref args, .. } = *kind { if let mir::Operand::Constant(ref func) = *oper { - if let ty::FnDef(def_id, _) = func.ty.sty { + if let ty::FnDef(def_id, _) = func.literal.ty.sty { let abi = tcx.fn_sig(def_id).abi(); let name = tcx.item_name(def_id); if abi == Abi::RustIntrinsic && name == sym::rustc_peek { diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index 52fd645e38e..c5561a1ae0d 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -970,7 +970,6 @@ where fn constant_usize(&self, val: u16) -> Operand<'tcx> { Operand::Constant(box Constant { span: self.source_info.span, - ty: self.tcx().types.usize, user_ty: None, literal: ty::Const::from_usize(self.tcx(), val.into()), }) diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs index 68880fc345a..ac2701971df 100644 --- a/src/librustc_mir/util/pretty.rs +++ b/src/librustc_mir/util/pretty.rs @@ -397,10 +397,9 @@ impl ExtraComments<'tcx> { impl Visitor<'tcx> for ExtraComments<'tcx> { fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) { self.super_constant(constant, location); - let Constant { span, ty, user_ty, literal } = constant; + let Constant { span, user_ty, literal } = constant; self.push("mir::Constant"); self.push(&format!("+ span: {:?}", span)); - self.push(&format!("+ ty: {:?}", ty)); if let Some(user_ty) = user_ty { self.push(&format!("+ user_ty: {:?}", user_ty)); } diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 3c31bcef32b..bd46ca4779a 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -602,7 +602,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } ItemKind::Enum(ref def, _) => { for variant in &def.variants { - for field in variant.node.data.fields() { + for field in variant.data.fields() { self.invalid_visibility(&field.vis, None); } } @@ -824,7 +824,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { |this| visit::walk_enum_def(this, enum_definition, generics, item_id)) } - fn visit_mac(&mut self, mac: &Spanned<Mac_>) { + fn visit_mac(&mut self, mac: &Mac) { // when a new macro kind is added but the author forgets to set it up for expansion // because that's the only part that won't cause a compiler error self.session.diagnostic() diff --git a/src/librustc_passes/loops.rs b/src/librustc_passes/loops.rs index afe4c78dcfc..1547e607b9c 100644 --- a/src/librustc_passes/loops.rs +++ b/src/librustc_passes/loops.rs @@ -7,7 +7,7 @@ use rustc::ty::TyCtxt; use rustc::hir::def_id::DefId; use rustc::hir::map::Map; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; -use rustc::hir::{self, Node, Destination}; +use rustc::hir::{self, Node, Destination, GeneratorMovability}; use syntax::struct_span_err; use syntax_pos::Span; use errors::Applicability; @@ -17,6 +17,7 @@ enum Context { Normal, Loop(hir::LoopSource), Closure, + AsyncClosure, LabeledBlock, AnonConst, } @@ -57,9 +58,14 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { hir::ExprKind::Loop(ref b, _, source) => { self.with_context(Loop(source), |v| v.visit_block(&b)); } - hir::ExprKind::Closure(_, ref function_decl, b, _, _) => { + hir::ExprKind::Closure(_, ref function_decl, b, _, movability) => { + let cx = if let Some(GeneratorMovability::Static) = movability { + AsyncClosure + } else { + Closure + }; self.visit_fn_decl(&function_decl); - self.with_context(Closure, |v| v.visit_nested_body(b)); + self.with_context(cx, |v| v.visit_nested_body(b)); } hir::ExprKind::Block(ref b, Some(_label)) => { self.with_context(LabeledBlock, |v| v.visit_block(&b)); @@ -171,6 +177,11 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> { .span_label(span, "cannot break inside of a closure") .emit(); } + AsyncClosure => { + struct_span_err!(self.sess, span, E0267, "`{}` inside of an async block", name) + .span_label(span, "cannot break inside of an async block") + .emit(); + } Normal | AnonConst => { struct_span_err!(self.sess, span, E0268, "`{}` outside of loop", name) .span_label(span, "cannot break outside of a loop") diff --git a/src/librustc_plugin/Cargo.toml b/src/librustc_plugin/Cargo.toml index 7486281c1ea..84a743ed1ad 100644 --- a/src/librustc_plugin/Cargo.toml +++ b/src/librustc_plugin/Cargo.toml @@ -1,12 +1,12 @@ [package] authors = ["The Rust Project Developers"] -name = "rustc_plugin" +name = "rustc_plugin_impl" version = "0.0.0" build = false edition = "2018" [lib] -name = "rustc_plugin" +name = "rustc_plugin_impl" path = "lib.rs" doctest = false diff --git a/src/librustc_plugin/deprecated/Cargo.toml b/src/librustc_plugin/deprecated/Cargo.toml new file mode 100644 index 00000000000..cc75f7b9ab2 --- /dev/null +++ b/src/librustc_plugin/deprecated/Cargo.toml @@ -0,0 +1,14 @@ +[package] +authors = ["The Rust Project Developers"] +name = "rustc_plugin" +version = "0.0.0" +build = false +edition = "2018" + +[lib] +name = "rustc_plugin" +path = "lib.rs" +doctest = false + +[dependencies] +rustc_plugin_impl = { path = ".." } diff --git a/src/librustc_plugin/deprecated/lib.rs b/src/librustc_plugin/deprecated/lib.rs new file mode 100644 index 00000000000..1d0afe84c25 --- /dev/null +++ b/src/librustc_plugin/deprecated/lib.rs @@ -0,0 +1,8 @@ +#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] +#![feature(staged_api)] +#![unstable(feature = "rustc_private", issue = "27812")] +#![rustc_deprecated(since = "1.38.0", reason = "\ + import this through `rustc_driver::plugin` instead to make TLS work correctly. \ + See https://github.com/rust-lang/rust/issues/62717")] + +pub use rustc_plugin_impl::*; diff --git a/src/librustc_plugin/lib.rs b/src/librustc_plugin/lib.rs index 25a7a8cdeb6..952bc9fff6a 100644 --- a/src/librustc_plugin/lib.rs +++ b/src/librustc_plugin/lib.rs @@ -16,12 +16,11 @@ //! #![feature(plugin_registrar)] //! #![feature(rustc_private)] //! -//! extern crate rustc_plugin; //! extern crate rustc_driver; //! extern crate syntax; //! extern crate syntax_pos; //! -//! use rustc_plugin::Registry; +//! use rustc_driver::plugin::Registry; //! use syntax::ext::base::{ExtCtxt, MacResult}; //! use syntax_pos::Span; //! use syntax::tokenstream::TokenTree; diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 673762ee4c6..bca77621e55 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -687,11 +687,11 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> { match item.node { hir::ItemKind::Enum(ref def, _) => { for variant in &def.variants { - let variant_level = self.update(variant.node.id, item_level); - if let Some(ctor_hir_id) = variant.node.data.ctor_hir_id() { + let variant_level = self.update(variant.id, item_level); + if let Some(ctor_hir_id) = variant.data.ctor_hir_id() { self.update(ctor_hir_id, item_level); } - for field in variant.node.data.fields() { + for field in variant.data.fields() { self.update(field.hir_id, variant_level); } } @@ -810,9 +810,9 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> { self.reach(item.hir_id, item_level).generics().predicates(); } for variant in &def.variants { - let variant_level = self.get(variant.node.id); + let variant_level = self.get(variant.id); if variant_level.is_some() { - for field in variant.node.data.fields() { + for field in variant.data.fields() { self.reach(field.hir_id, variant_level).ty(); } // Corner case: if the variant is reachable, but its @@ -1075,8 +1075,8 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> { let adt = self.tables.pat_ty(pat).ty_adt_def().unwrap(); let variant = adt.variant_of_res(res); for field in fields { - let use_ctxt = field.node.ident.span; - let index = self.tcx.field_index(field.node.hir_id, self.tables); + let use_ctxt = field.ident.span; + let index = self.tcx.field_index(field.hir_id, self.tables); self.check_field(use_ctxt, field.span, adt, &variant.fields[index]); } } @@ -1647,7 +1647,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { v: &'tcx hir::Variant, g: &'tcx hir::Generics, item_id: hir::HirId) { - if self.access_levels.is_reachable(v.node.id) { + if self.access_levels.is_reachable(v.id) { self.in_variant = true; intravisit::walk_variant(self, v, g, item_id); self.in_variant = false; @@ -1898,7 +1898,7 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> self.check(item.hir_id, item_visibility).generics().predicates(); for variant in &def.variants { - for field in variant.node.data.fields() { + for field in variant.data.fields() { self.check(field.hir_id, item_visibility).ty(); } } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 5dd7bc30548..42428456b6e 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -1,9 +1,11 @@ -//! Reduced graph building. +//! After we obtain a fresh AST fragment from a macro, code in this module helps to integrate +//! that fragment into the module structures that are already partially built. //! -//! Here we build the "reduced graph": the graph of the module tree without -//! any imports resolved. +//! Items from the fragment are placed into modules, +//! unexpanded macros in the fragment are visited and registered. +//! Imports are also considered items and placed into modules here, but not resolved yet. -use crate::macros::{InvocationData, LegacyBinding, LegacyScope}; +use crate::macros::{LegacyBinding, LegacyScope}; use crate::resolve_imports::ImportDirective; use crate::resolve_imports::ImportDirectiveSubclass::{self, GlobImport, SingleImport}; use crate::{Module, ModuleData, ModuleKind, NameBinding, NameBindingKind, Segment, ToNameBinding}; @@ -14,6 +16,7 @@ use crate::{ResolutionError, Determinacy, PathResult, CrateLint}; use rustc::bug; use rustc::hir::def::{self, *}; use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId}; +use rustc::hir::map::DefCollector; use rustc::ty; use rustc::middle::cstore::CrateStore; use rustc_metadata::cstore::LoadedMacro; @@ -30,6 +33,7 @@ use syntax::attr; use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind, NodeId}; use syntax::ast::{MetaItemKind, StmtKind, TraitItem, TraitItemKind, Variant}; use syntax::ext::base::{MacroKind, SyntaxExtension}; +use syntax::ext::expand::AstFragment; use syntax::ext::hygiene::ExpnId; use syntax::feature_gate::is_builtin_attr; use syntax::parse::token::{self, Token}; @@ -67,7 +71,7 @@ impl<'a> ToNameBinding<'a> for (Res, ty::Visibility, Span, ExpnId) { } } -pub(crate) struct IsMacroExport; +struct IsMacroExport; impl<'a> ToNameBinding<'a> for (Res, ty::Visibility, Span, ExpnId, IsMacroExport) { fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> { @@ -84,7 +88,7 @@ impl<'a> ToNameBinding<'a> for (Res, ty::Visibility, Span, ExpnId, IsMacroExport impl<'a> Resolver<'a> { /// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined; /// otherwise, reports an error. - pub fn define<T>(&mut self, parent: Module<'a>, ident: Ident, ns: Namespace, def: T) + crate fn define<T>(&mut self, parent: Module<'a>, ident: Ident, ns: Namespace, def: T) where T: ToNameBinding<'a>, { let binding = def.to_name_binding(self.arenas); @@ -93,7 +97,7 @@ impl<'a> Resolver<'a> { } } - pub fn get_module(&mut self, def_id: DefId) -> Module<'a> { + crate fn get_module(&mut self, def_id: DefId) -> Module<'a> { if def_id.krate == LOCAL_CRATE { return self.module_map[&def_id] } @@ -119,7 +123,7 @@ impl<'a> Resolver<'a> { module } - pub fn macro_def_scope(&mut self, expn_id: ExpnId) -> Module<'a> { + crate fn macro_def_scope(&mut self, expn_id: ExpnId) -> Module<'a> { let def_id = match self.macro_defs.get(&expn_id) { Some(def_id) => *def_id, None => return self.graph_root, @@ -141,7 +145,7 @@ impl<'a> Resolver<'a> { } } - crate fn get_macro_by_def_id(&mut self, def_id: DefId) -> Option<Lrc<SyntaxExtension>> { + fn get_macro_by_def_id(&mut self, def_id: DefId) -> Option<Lrc<SyntaxExtension>> { if let Some(ext) = self.macro_map.get(&def_id) { return Some(ext.clone()); } @@ -156,23 +160,45 @@ impl<'a> Resolver<'a> { Some(ext) } - /// Ensures that the reduced graph rooted at the given external module - /// is built, building it if it is not. - pub fn populate_module_if_necessary(&mut self, module: Module<'a>) { - if module.populated.get() { return } - let def_id = module.def_id().unwrap(); + // FIXME: `extra_placeholders` should be included into the `fragment` as regular placeholders. + crate fn build_reduced_graph( + &mut self, + fragment: &AstFragment, + extra_placeholders: &[NodeId], + parent_scope: ParentScope<'a>, + ) -> LegacyScope<'a> { + let mut def_collector = DefCollector::new(&mut self.definitions, parent_scope.expansion); + fragment.visit_with(&mut def_collector); + for placeholder in extra_placeholders { + def_collector.visit_macro_invoc(*placeholder); + } + + let mut visitor = BuildReducedGraphVisitor { r: self, parent_scope }; + fragment.visit_with(&mut visitor); + for placeholder in extra_placeholders { + visitor.parent_scope.legacy = visitor.visit_invoc(*placeholder); + } + + visitor.parent_scope.legacy + } + + 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) { let child = child.map_id(|_| panic!("unexpected id")); - BuildReducedGraphVisitor { parent_scope: self.dummy_parent_scope(), r: self } - .build_reduced_graph_for_external_crate_res(module, child); + BuildReducedGraphVisitor { r: self, parent_scope: ParentScope::module(module) } + .build_reduced_graph_for_external_crate_res(child); } - module.populated.set(true) } } -pub struct BuildReducedGraphVisitor<'a, 'b> { - pub r: &'b mut Resolver<'a>, - pub parent_scope: ParentScope<'a>, +struct BuildReducedGraphVisitor<'a, 'b> { + r: &'b mut Resolver<'a>, + parent_scope: ParentScope<'a>, +} + +impl<'a> AsMut<Resolver<'a>> for BuildReducedGraphVisitor<'a, '_> { + fn as_mut(&mut self) -> &mut Resolver<'a> { self.r } } impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { @@ -300,10 +326,9 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { root_id: NodeId, vis: ty::Visibility, ) { - let parent_scope = &self.parent_scope; - let current_module = parent_scope.module; + let current_module = self.parent_scope.module; let directive = self.r.arenas.alloc_import_directive(ImportDirective { - parent_scope: parent_scope.clone(), + parent_scope: self.parent_scope, module_path, imported_module: Cell::new(None), subclass, @@ -593,15 +618,13 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { self.r.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }) }; - self.r.populate_module_if_necessary(module); - let used = self.process_legacy_macro_imports(item, module); let binding = (module, ty::Visibility::Public, sp, expansion).to_name_binding(self.r.arenas); let directive = self.r.arenas.alloc_import_directive(ImportDirective { root_id: item.id, id: item.id, - parent_scope: self.parent_scope.clone(), + parent_scope: self.parent_scope, imported_module: Cell::new(Some(ModuleOrUniformRoot::Module(module))), subclass: ImportDirectiveSubclass::ExternCrate { source: orig_name, @@ -706,7 +729,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { self.r.define(parent, ident, TypeNS, (module, vis, sp, expansion)); for variant in &(*enum_definition).variants { - self.build_reduced_graph_for_variant(variant, module, vis, expansion); + self.build_reduced_graph_for_variant(variant, module, vis); } } @@ -797,19 +820,19 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { fn build_reduced_graph_for_variant(&mut self, variant: &Variant, parent: Module<'a>, - vis: ty::Visibility, - expn_id: ExpnId) { - let ident = variant.node.ident; + vis: ty::Visibility) { + let expn_id = self.parent_scope.expansion; + let ident = variant.ident; // Define a name in the type namespace. - let def_id = self.r.definitions.local_def_id(variant.node.id); + let def_id = self.r.definitions.local_def_id(variant.id); let res = Res::Def(DefKind::Variant, def_id); self.r.define(parent, ident, TypeNS, (res, vis, variant.span, expn_id)); // If the variant is marked as non_exhaustive then lower the visibility to within the // crate. let mut ctor_vis = vis; - let has_non_exhaustive = attr::contains_name(&variant.node.attrs, sym::non_exhaustive); + let has_non_exhaustive = attr::contains_name(&variant.attrs, sym::non_exhaustive); if has_non_exhaustive && vis == ty::Visibility::Public { ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)); } @@ -819,9 +842,9 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { // value namespace, they are reserved for possible future use. // It's ok to use the variant's id as a ctor id since an // error will be reported on any use of such resolution anyway. - let ctor_node_id = variant.node.data.ctor_id().unwrap_or(variant.node.id); + let ctor_node_id = variant.data.ctor_id().unwrap_or(variant.id); let ctor_def_id = self.r.definitions.local_def_id(ctor_node_id); - let ctor_kind = CtorKind::from_ast(&variant.node.data); + let ctor_kind = CtorKind::from_ast(&variant.data); let ctor_res = Res::Def(DefKind::Ctor(CtorOf::Variant, ctor_kind), ctor_def_id); self.r.define(parent, ident, ValueNS, (ctor_res, ctor_vis, variant.span, expn_id)); } @@ -861,20 +884,19 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { } /// Builds the reduced graph for a single item in an external crate. - fn build_reduced_graph_for_external_crate_res( - &mut self, - parent: Module<'a>, - child: Export<ast::NodeId>, - ) { + fn build_reduced_graph_for_external_crate_res(&mut self, child: Export<NodeId>) { + let parent = self.parent_scope.module; let Export { ident, res, vis, span } = child; // FIXME: We shouldn't create the gensym here, it should come from metadata, // but metadata cannot encode gensyms currently, so we create it here. // This is only a guess, two equivalent idents may incorrectly get different gensyms here. let ident = ident.gensym_if_underscore(); let expansion = ExpnId::root(); // FIXME(jseyfried) intercrate hygiene + // Record primary definitions. match res { Res::Def(kind @ DefKind::Mod, def_id) - | Res::Def(kind @ DefKind::Enum, def_id) => { + | Res::Def(kind @ DefKind::Enum, def_id) + | Res::Def(kind @ DefKind::Trait, def_id) => { let module = self.r.new_module(parent, ModuleKind::Def(kind, def_id, ident.name), def_id, @@ -882,70 +904,55 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { span); self.r.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, expansion)); } - Res::Def(DefKind::Variant, _) + Res::Def(DefKind::Struct, _) + | Res::Def(DefKind::Union, _) + | Res::Def(DefKind::Variant, _) | Res::Def(DefKind::TyAlias, _) | Res::Def(DefKind::ForeignTy, _) | Res::Def(DefKind::OpaqueTy, _) | Res::Def(DefKind::TraitAlias, _) + | Res::Def(DefKind::AssocTy, _) + | Res::Def(DefKind::AssocOpaqueTy, _) | Res::PrimTy(..) - | Res::ToolMod => { - self.r.define(parent, ident, TypeNS, (res, vis, DUMMY_SP, expansion)); - } + | Res::ToolMod => + self.r.define(parent, ident, TypeNS, (res, vis, DUMMY_SP, expansion)), Res::Def(DefKind::Fn, _) + | Res::Def(DefKind::Method, _) | Res::Def(DefKind::Static, _) | Res::Def(DefKind::Const, _) - | Res::Def(DefKind::Ctor(CtorOf::Variant, ..), _) => { - self.r.define(parent, ident, ValueNS, (res, vis, DUMMY_SP, expansion)); - } - Res::Def(DefKind::Ctor(CtorOf::Struct, ..), def_id) => { - self.r.define(parent, ident, ValueNS, (res, vis, DUMMY_SP, expansion)); - - if let Some(struct_def_id) = - self.r.cstore.def_key(def_id).parent - .map(|index| DefId { krate: def_id.krate, index: index }) { - self.r.struct_constructors.insert(struct_def_id, (res, vis)); - } - } - Res::Def(DefKind::Trait, def_id) => { - let module_kind = ModuleKind::Def(DefKind::Trait, def_id, ident.name); - let module = self.r.new_module(parent, - module_kind, - parent.normal_ancestor_id, - expansion, - span); - self.r.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, expansion)); - - for child in self.r.cstore.item_children_untracked(def_id, self.r.session) { - let res = child.res.map_id(|_| panic!("unexpected id")); - let ns = if let Res::Def(DefKind::AssocTy, _) = res { - TypeNS - } else { ValueNS }; - self.r.define(module, child.ident, ns, - (res, ty::Visibility::Public, DUMMY_SP, expansion)); - - if self.r.cstore.associated_item_cloned_untracked(child.res.def_id()) - .method_has_self_argument { - self.r.has_self.insert(res.def_id()); - } - } - module.populated.set(true); - } + | Res::Def(DefKind::AssocConst, _) + | Res::Def(DefKind::Ctor(..), _) => + self.r.define(parent, ident, ValueNS, (res, vis, DUMMY_SP, expansion)), + Res::Def(DefKind::Macro(..), _) + | Res::NonMacroAttr(..) => + self.r.define(parent, ident, MacroNS, (res, vis, DUMMY_SP, expansion)), + Res::Def(DefKind::TyParam, _) | Res::Def(DefKind::ConstParam, _) + | Res::Local(..) | Res::SelfTy(..) | Res::SelfCtor(..) | Res::Err => + bug!("unexpected resolution: {:?}", res) + } + // Record some extra data for better diagnostics. + match res { Res::Def(DefKind::Struct, def_id) | Res::Def(DefKind::Union, def_id) => { - self.r.define(parent, ident, TypeNS, (res, vis, DUMMY_SP, expansion)); - - // Record field names for error reporting. let field_names = self.r.cstore.struct_field_names_untracked(def_id); self.insert_field_names(def_id, field_names); } - Res::Def(DefKind::Macro(..), _) | Res::NonMacroAttr(..) => { - self.r.define(parent, ident, MacroNS, (res, vis, DUMMY_SP, expansion)); + Res::Def(DefKind::Method, def_id) => { + if self.r.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; + if let Some(struct_def_id) = parent.map(|index| DefId { index, ..def_id }) { + self.r.struct_constructors.insert(struct_def_id, (res, vis)); + } } - _ => bug!("unexpected resolution: {:?}", res) + _ => {} } } fn legacy_import_macro(&mut self, - name: Name, + name: ast::Name, binding: &'a NameBinding<'a>, span: Span, allow_shadowing: bool) { @@ -997,7 +1004,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { |this: &Self, span| this.r.arenas.alloc_import_directive(ImportDirective { root_id: item.id, id: item.id, - parent_scope: this.parent_scope.clone(), + parent_scope: this.parent_scope, imported_module: Cell::new(Some(ModuleOrUniformRoot::Module(module))), subclass: ImportDirectiveSubclass::MacroUse, use_span_with_attributes: item.span_with_attributes(), @@ -1014,9 +1021,9 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { if let Some(span) = import_all { let directive = macro_use_directive(self, span); self.r.potentially_unused_imports.push(directive); - module.for_each_child(|ident, ns, binding| if ns == MacroNS { - let imported_binding = self.r.import(binding, directive); - self.legacy_import_macro(ident.name, imported_binding, span, allow_shadowing); + module.for_each_child(self, |this, ident, ns, binding| if ns == MacroNS { + let imported_binding = this.r.import(binding, directive); + this.legacy_import_macro(ident.name, imported_binding, span, allow_shadowing); }); } else { for ident in single_imports.iter().cloned() { @@ -1066,20 +1073,15 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { false } - fn visit_invoc(&mut self, id: ast::NodeId) -> &'a InvocationData<'a> { + fn visit_invoc(&mut self, id: NodeId) -> LegacyScope<'a> { let invoc_id = id.placeholder_to_expn_id(); - self.parent_scope.module.unresolved_invocations.borrow_mut().insert(invoc_id); + self.parent_scope.module.unexpanded_invocations.borrow_mut().insert(invoc_id); - let invocation_data = self.r.arenas.alloc_invocation_data(InvocationData { - module: self.parent_scope.module, - parent_legacy_scope: self.parent_scope.legacy, - output_legacy_scope: Cell::new(None), - }); - let old_invocation_data = self.r.invocations.insert(invoc_id, invocation_data); - assert!(old_invocation_data.is_none(), "invocation data is reset for an invocation"); + let old_parent_scope = self.r.invocation_parent_scopes.insert(invoc_id, self.parent_scope); + assert!(old_parent_scope.is_none(), "invocation data is reset for an invocation"); - invocation_data + LegacyScope::Invocation(invoc_id) } fn proc_macro_stub(item: &ast::Item) -> Option<(MacroKind, Ident, Span)> { @@ -1180,7 +1182,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> { return } ItemKind::Mac(..) => { - self.parent_scope.legacy = LegacyScope::Invocation(self.visit_invoc(item.id)); + self.parent_scope.legacy = self.visit_invoc(item.id); return } ItemKind::Mod(..) => self.contains_macro_use(&item.attrs), @@ -1199,7 +1201,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> { fn visit_stmt(&mut self, stmt: &'b ast::Stmt) { if let ast::StmtKind::Mac(..) = stmt.node { - self.parent_scope.legacy = LegacyScope::Invocation(self.visit_invoc(stmt.id)); + self.parent_scope.legacy = self.visit_invoc(stmt.id); } else { visit::walk_stmt(self, stmt); } @@ -1267,9 +1269,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> { fn visit_attribute(&mut self, attr: &'b ast::Attribute) { if !attr.is_sugared_doc && is_builtin_attr(attr) { - self.parent_scope.module.builtin_attrs.borrow_mut().push(( - attr.path.segments[0].ident, self.parent_scope.clone() - )); + self.r.builtin_attrs.push((attr.path.segments[0].ident, self.parent_scope)); } visit::walk_attribute(self, attr); } diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 1de67edb95c..b79e0c2bd3b 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -73,20 +73,23 @@ crate fn add_typo_suggestion( false } -crate fn add_module_candidates( - module: Module<'_>, names: &mut Vec<TypoSuggestion>, filter_fn: &impl Fn(Res) -> bool -) { - for (&(ident, _), resolution) in module.resolutions.borrow().iter() { - if let Some(binding) = resolution.borrow().binding { - let res = binding.res(); - if filter_fn(res) { - names.push(TypoSuggestion::from_res(ident.name, res)); +impl<'a> Resolver<'a> { + crate fn add_module_candidates( + &mut self, + module: Module<'a>, + names: &mut Vec<TypoSuggestion>, + filter_fn: &impl Fn(Res) -> bool, + ) { + for (&(ident, _), resolution) in self.resolutions(module).borrow().iter() { + if let Some(binding) = resolution.borrow().binding { + let res = binding.res(); + if filter_fn(res) { + names.push(TypoSuggestion::from_res(ident.name, res)); + } } } } -} -impl<'a> Resolver<'a> { /// Combines an error with provided span and emits it. /// /// This takes the error provided, combines it with the span and any additional spans inside the @@ -166,12 +169,14 @@ impl<'a> Resolver<'a> { err } ResolutionError::NameAlreadyUsedInParameterList(name, first_use_span) => { - let mut err = struct_span_err!(self.session, - span, - E0403, - "the name `{}` is already used for a generic \ - parameter in this list of generic parameters", - name); + let mut err = struct_span_err!( + self.session, + span, + E0403, + "the name `{}` is already used for a generic \ + parameter in this item's generic parameters", + name, + ); err.span_label(span, "already used"); err.span_label(first_use_span, format!("first use of `{}`", name)); err @@ -376,9 +381,9 @@ impl<'a> Resolver<'a> { Scope::DeriveHelpers => { let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper); if filter_fn(res) { - for derive in &parent_scope.derives { + for derive in parent_scope.derives { let parent_scope = - &ParentScope { derives: Vec::new(), ..*parent_scope }; + &ParentScope { derives: &[], ..*parent_scope }; if let Ok((Some(ext), _)) = this.resolve_macro_path( derive, Some(MacroKind::Derive), parent_scope, false, false ) { @@ -402,10 +407,10 @@ impl<'a> Resolver<'a> { Scope::CrateRoot => { let root_ident = Ident::new(kw::PathRoot, ident.span); let root_module = this.resolve_crate_root(root_ident); - add_module_candidates(root_module, &mut suggestions, filter_fn); + this.add_module_candidates(root_module, &mut suggestions, filter_fn); } Scope::Module(module) => { - add_module_candidates(module, &mut suggestions, filter_fn); + this.add_module_candidates(module, &mut suggestions, filter_fn); } Scope::MacroUsePrelude => { suggestions.extend(this.macro_use_prelude.iter().filter_map(|(name, binding)| { @@ -453,9 +458,9 @@ impl<'a> Resolver<'a> { Scope::StdLibPrelude => { if let Some(prelude) = this.prelude { let mut tmp_suggestions = Vec::new(); - add_module_candidates(prelude, &mut tmp_suggestions, filter_fn); + this.add_module_candidates(prelude, &mut tmp_suggestions, filter_fn); suggestions.extend(tmp_suggestions.into_iter().filter(|s| { - use_prelude || this.is_builtin_macro(s.res.opt_def_id()) + use_prelude || this.is_builtin_macro(s.res) })); } } @@ -509,11 +514,9 @@ impl<'a> Resolver<'a> { while let Some((in_module, path_segments, in_module_is_extern)) = worklist.pop() { - self.populate_module_if_necessary(in_module); - // We have to visit module children in deterministic order to avoid // instabilities in reported imports (#43552). - in_module.for_each_child_stable(|ident, ns, name_binding| { + in_module.for_each_child_stable(self, |this, ident, ns, name_binding| { // avoid imports entirely if name_binding.is_import() && !name_binding.is_extern_crate() { return; } // avoid non-importable candidates as well @@ -547,7 +550,7 @@ impl<'a> Resolver<'a> { // outside crate private modules => no need to check this) if !in_module_is_extern || name_binding.vis == ty::Visibility::Public { let did = match res { - Res::Def(DefKind::Ctor(..), did) => self.parent(did), + Res::Def(DefKind::Ctor(..), did) => this.parent(did), _ => res.opt_def_id(), }; candidates.push(ImportSuggestion { did, path }); @@ -595,7 +598,7 @@ impl<'a> Resolver<'a> { where FilterFn: Fn(Res) -> bool { let mut suggestions = self.lookup_import_candidates_from_module( - lookup_ident, namespace, self.graph_root, Ident::with_empty_ctxt(kw::Crate), &filter_fn + lookup_ident, namespace, self.graph_root, Ident::with_dummy_span(kw::Crate), &filter_fn ); if lookup_ident.span.rust_2018() { @@ -607,8 +610,6 @@ impl<'a> Resolver<'a> { krate: crate_id, index: CRATE_DEF_INDEX, }); - self.populate_module_if_necessary(&crate_root); - suggestions.extend(self.lookup_import_candidates_from_module( lookup_ident, namespace, crate_root, ident, &filter_fn)); } @@ -805,7 +806,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { /// at the root of the crate instead of the module where it is defined /// ``` pub(crate) fn check_for_module_export_macro( - &self, + &mut self, directive: &'b ImportDirective<'b>, module: ModuleOrUniformRoot<'b>, ident: Ident, @@ -826,7 +827,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { return None; } - let resolutions = crate_module.resolutions.borrow(); + let resolutions = self.r.resolutions(crate_module).borrow(); let resolution = resolutions.get(&(ident, MacroNS))?; let binding = resolution.borrow().binding()?; if let Res::Def(DefKind::Macro(MacroKind::Bang), _) = binding.res() { diff --git a/src/librustc_resolve/error_codes.rs b/src/librustc_resolve/error_codes.rs index e01f53786ed..1faaf97e981 100644 --- a/src/librustc_resolve/error_codes.rs +++ b/src/librustc_resolve/error_codes.rs @@ -526,15 +526,25 @@ Some type parameters have the same name. Erroneous code example: ```compile_fail,E0403 -fn foo<T, T>(s: T, u: T) {} // error: the name `T` is already used for a type - // parameter in this type parameter list +fn f<T, T>(s: T, u: T) {} // error: the name `T` is already used for a generic + // parameter in this item's generic parameters ``` Please verify that none of the type parameters are misspelled, and rename any clashing parameters. Example: ``` -fn foo<T, Y>(s: T, u: Y) {} // ok! +fn f<T, Y>(s: T, u: Y) {} // ok! +``` + +Type parameters in an associated item also cannot shadow parameters from the +containing item: + +```compile_fail,E0403 +trait Foo<T> { + fn do_something(&self) -> T; + fn do_something_else<T: Clone>(&self, bar: T); +} ``` "##, diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index 358eaae11e7..e15d02a9f7e 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -1,3 +1,10 @@ +//! "Late resolution" is the pass that resolves most of names in a crate beside imports and macros. +//! It runs when the crate is fully expanded and its module structure is fully built. +//! So it just walks through the crate and resolves all the expressions, types, etc. +//! +//! If you wonder why there's no `early.rs`, that's because it's split into three files - +//! `build_reduced_graph.rs`, `macros.rs` and `resolve_imports.rs`. + use GenericParameters::*; use RibKind::*; @@ -104,6 +111,24 @@ crate enum RibKind<'a> { TyParamAsConstParamTy, } +impl RibKind<'_> { + // Whether this rib kind contains generic parameters, as opposed to local + // variables. + crate fn contains_params(&self) -> bool { + match self { + NormalRibKind + | FnItemRibKind + | ConstantItemRibKind + | ModuleRibKind(_) + | MacroDefinition(_) => false, + AssocItemRibKind + | ItemRibKind + | ForwardTyParamBanRibKind + | TyParamAsConstParamTy => true, + } + } +} + /// A single local scope. /// /// A rib represents a scope names can live in. Note that these appear in many places, not just @@ -352,7 +377,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LateResolutionVisitor<'a, '_> { self.smart_resolve_path(ty.id, qself.as_ref(), path, PathSource::Type); } TyKind::ImplicitSelf => { - let self_ty = Ident::with_empty_ctxt(kw::SelfUpper); + let self_ty = Ident::with_dummy_span(kw::SelfUpper); let res = self.resolve_ident_in_lexical_scope(self_ty, TypeNS, Some(ty.id), ty.span) .map_or(Res::Err, |d| d.res()); self.r.record_partial_res(ty.id, PartialRes::new(res)); @@ -442,7 +467,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LateResolutionVisitor<'a, '_> { GenericParamKind::Type { ref default, .. } => { found_default |= default.is_some(); if found_default { - Some((Ident::with_empty_ctxt(param.ident.name), Res::Err)) + Some((Ident::with_dummy_span(param.ident.name), Res::Err)) } else { None } @@ -459,7 +484,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LateResolutionVisitor<'a, '_> { false } }) - .map(|param| (Ident::with_empty_ctxt(param.ident.name), Res::Err))); + .map(|param| (Ident::with_dummy_span(param.ident.name), Res::Err))); for param in &generics.params { match param.kind { @@ -476,7 +501,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LateResolutionVisitor<'a, '_> { } // Allow all following defaults to refer to this type parameter. - default_ban_rib.bindings.remove(&Ident::with_empty_ctxt(param.ident.name)); + 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); @@ -501,8 +526,8 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { fn new(resolver: &'b mut Resolver<'a>) -> LateResolutionVisitor<'a, 'b> { // During late resolution we only track the module component of the parent scope, // although it may be useful to track other components as well for diagnostics. - let parent_scope = resolver.dummy_parent_scope(); let graph_root = resolver.graph_root; + let parent_scope = ParentScope::module(graph_root); LateResolutionVisitor { r: resolver, parent_scope, @@ -574,7 +599,6 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { self.ribs[ValueNS].push(Rib::new(ModuleRibKind(module))); self.ribs[TypeNS].push(Rib::new(ModuleRibKind(module))); - self.r.finalize_current_module_macro_resolutions(module); let ret = f(self); self.parent_scope.module = orig_module; @@ -792,6 +816,19 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { let mut function_type_rib = Rib::new(rib_kind); let mut function_value_rib = Rib::new(rib_kind); let mut seen_bindings = FxHashMap::default(); + // We also can't shadow bindings from the parent item + if let AssocItemRibKind = rib_kind { + let mut add_bindings_for_ns = |ns| { + let parent_rib = self.ribs[ns].iter() + .rfind(|rib| if let ItemRibKind = rib.kind { true } else { false }) + .expect("associated item outside of an item"); + seen_bindings.extend( + parent_rib.bindings.iter().map(|(ident, _)| (*ident, ident.span)), + ); + }; + add_bindings_for_ns(ValueNS); + add_bindings_for_ns(TypeNS); + } for param in &generics.params { match param.kind { GenericParamKind::Lifetime { .. } => {} @@ -965,7 +1002,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { let mut self_type_rib = Rib::new(NormalRibKind); // Plain insert (no renaming, since types are not currently hygienic) - self_type_rib.bindings.insert(Ident::with_empty_ctxt(kw::SelfUpper), self_res); + self_type_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), self_res); self.ribs[TypeNS].push(self_type_rib); f(self); self.ribs[TypeNS].pop(); @@ -976,7 +1013,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { { let self_res = Res::SelfCtor(impl_id); let mut self_type_rib = Rib::new(NormalRibKind); - self_type_rib.bindings.insert(Ident::with_empty_ctxt(kw::SelfUpper), self_res); + self_type_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), self_res); self.ribs[ValueNS].push(self_type_rib); f(self); self.ribs[ValueNS].pop(); @@ -1227,7 +1264,6 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { self.ribs[ValueNS].push(Rib::new(ModuleRibKind(anonymous_module))); self.ribs[TypeNS].push(Rib::new(ModuleRibKind(anonymous_module))); self.parent_scope.module = anonymous_module; - self.r.finalize_current_module_macro_resolutions(anonymous_module); } else { self.ribs[ValueNS].push(Rib::new(NormalRibKind)); } @@ -1476,7 +1512,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { self.r.trait_map.insert(id, traits); } - let mut std_path = vec![Segment::from_ident(Ident::with_empty_ctxt(sym::std))]; + let mut std_path = vec![Segment::from_ident(Ident::with_dummy_span(sym::std))]; std_path.extend(path); if self.r.primitive_type_table.primitive_types.contains_key(&path[0].ident.name) { let cl = CrateLint::No; @@ -1507,7 +1543,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { fn self_type_is_available(&mut self, span: Span) -> bool { let binding = self.resolve_ident_in_lexical_scope( - Ident::with_empty_ctxt(kw::SelfUpper), + Ident::with_dummy_span(kw::SelfUpper), TypeNS, None, span, @@ -1924,7 +1960,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { let mut traits = module.traits.borrow_mut(); if traits.is_none() { let mut collected_traits = Vec::new(); - module.for_each_child(|name, ns, binding| { + module.for_each_child(self.r, |_, name, ns, binding| { if ns != TypeNS { return } match binding.res() { Res::Def(DefKind::Trait, _) | @@ -1984,7 +2020,6 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { impl<'a> Resolver<'a> { pub(crate) fn late_resolve_crate(&mut self, krate: &Crate) { - self.finalize_current_module_macro_resolutions(self.graph_root); let mut late_resolution_visitor = LateResolutionVisitor::new(self); visit::walk_crate(&mut late_resolution_visitor, krate); for (id, span) in late_resolution_visitor.unused_labels.iter() { diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs index 68f9c1684d6..a822fa049ca 100644 --- a/src/librustc_resolve/late/diagnostics.rs +++ b/src/librustc_resolve/late/diagnostics.rs @@ -1,8 +1,7 @@ use crate::{CrateLint, Module, ModuleKind, ModuleOrUniformRoot}; use crate::{PathResult, PathSource, Segment}; use crate::path_names_to_string; -use crate::diagnostics::{add_typo_suggestion, add_module_candidates}; -use crate::diagnostics::{ImportSuggestion, TypoSuggestion}; +use crate::diagnostics::{add_typo_suggestion, ImportSuggestion, TypoSuggestion}; use crate::late::{LateResolutionVisitor, RibKind}; use errors::{Applicability, DiagnosticBuilder, DiagnosticId}; @@ -548,7 +547,7 @@ impl<'a> LateResolutionVisitor<'a, '_> { // Items in scope if let RibKind::ModuleRibKind(module) = rib.kind { // Items from this module - add_module_candidates(module, &mut names, &filter_fn); + self.r.add_module_candidates(module, &mut names, &filter_fn); if let ModuleKind::Block(..) = module.kind { // We can see through blocks @@ -577,7 +576,7 @@ impl<'a> LateResolutionVisitor<'a, '_> { })); if let Some(prelude) = self.r.prelude { - add_module_candidates(prelude, &mut names, &filter_fn); + self.r.add_module_candidates(prelude, &mut names, &filter_fn); } } break; @@ -599,7 +598,7 @@ impl<'a> LateResolutionVisitor<'a, '_> { mod_path, Some(TypeNS), false, span, CrateLint::No ) { if let ModuleOrUniformRoot::Module(module) = module { - add_module_candidates(module, &mut names, &filter_fn); + self.r.add_module_candidates(module, &mut names, &filter_fn); } } } @@ -717,9 +716,7 @@ impl<'a> LateResolutionVisitor<'a, '_> { // abort if the module is already found if result.is_some() { break; } - self.r.populate_module_if_necessary(in_module); - - in_module.for_each_child_stable(|ident, _, name_binding| { + in_module.for_each_child_stable(self.r, |_, ident, _, name_binding| { // abort if the module is already found or if name_binding is private external if result.is_some() || !name_binding.vis.is_visible_locally() { return @@ -750,10 +747,8 @@ impl<'a> LateResolutionVisitor<'a, '_> { fn collect_enum_variants(&mut self, def_id: DefId) -> Option<Vec<Path>> { self.find_module(def_id).map(|(enum_module, enum_import_suggestion)| { - self.r.populate_module_if_necessary(enum_module); - let mut variants = Vec::new(); - enum_module.for_each_child_stable(|ident, _, name_binding| { + enum_module.for_each_child_stable(self.r, |_, ident, _, name_binding| { if let Res::Def(DefKind::Variant, _) = name_binding.res() { let mut segms = enum_import_suggestion.path.segments.clone(); segms.push(ast::PathSegment::from_ident(ident)); diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 8a4a60c16b0..2dd0ad13c52 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1,3 +1,12 @@ +//! This crate is responsible for the part of name resolution that doesn't require type checker. +//! +//! Module structure of the crate is built here. +//! Paths in macros, imports, expressions, types, patterns are resolved here. +//! Label names are resolved here as well. +//! +//! Type-relative name resolution (methods, fields, associated items) happens in `librustc_typeck`. +//! Lifetime names are resolved in `librustc/middle/resolve_lifetime.rs`. + #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] #![feature(crate_visibility_modifier)] @@ -54,7 +63,7 @@ use diagnostics::{Suggestion, ImportSuggestion}; use diagnostics::{find_span_of_binding_until_next_binding, extend_span_to_previous_binding}; use late::{PathSource, Rib, RibKind::*}; use resolve_imports::{ImportDirective, ImportDirectiveSubclass, NameResolution, ImportResolver}; -use macros::{InvocationData, LegacyBinding, LegacyScope}; +use macros::{LegacyBinding, LegacyScope}; type Res = def::Res<NodeId>; @@ -122,12 +131,25 @@ enum ScopeSet { /// Serves as a starting point for the scope visitor. /// This struct is currently used only for early resolution (imports and macros), /// but not for late resolution yet. -#[derive(Clone, Debug)] +#[derive(Clone, Copy, Debug)] pub struct ParentScope<'a> { module: Module<'a>, expansion: ExpnId, legacy: LegacyScope<'a>, - derives: Vec<ast::Path>, + derives: &'a [ast::Path], +} + +impl<'a> ParentScope<'a> { + /// Creates a parent scope with the passed argument used as the module scope component, + /// and other scope components set to default empty values. + pub fn module(module: Module<'a>) -> ParentScope<'a> { + ParentScope { + module, + expansion: ExpnId::root(), + legacy: LegacyScope::Empty, + derives: &[], + } + } } #[derive(Eq)] @@ -274,7 +296,7 @@ impl<'tcx> Visitor<'tcx> for UsePlacementFinder { ItemKind::Use(..) => { // don't suggest placing a use before the prelude // import or other generated ones - if item.span.ctxt().outer_expn_info().is_none() { + if !item.span.from_expansion() { self.span = Some(item.span.shrink_to_lo()); self.found_use = true; return; @@ -284,7 +306,7 @@ impl<'tcx> Visitor<'tcx> for UsePlacementFinder { ItemKind::ExternCrate(_) => {} // but place them before the first other item _ => if self.span.map_or(true, |span| item.span < span ) { - if item.span.ctxt().outer_expn_info().is_none() { + if !item.span.from_expansion() { // don't insert between attributes and an item if item.attrs.is_empty() { self.span = Some(item.span.shrink_to_lo()); @@ -409,6 +431,8 @@ impl ModuleKind { } } +type Resolutions<'a> = RefCell<FxHashMap<(Ident, Namespace), &'a RefCell<NameResolution<'a>>>>; + /// One node in the tree of modules. pub struct ModuleData<'a> { parent: Option<Module<'a>>, @@ -417,15 +441,14 @@ pub struct ModuleData<'a> { // The def id of the closest normal module (`mod`) ancestor (including this module). normal_ancestor_id: DefId, - resolutions: RefCell<FxHashMap<(Ident, Namespace), &'a RefCell<NameResolution<'a>>>>, - single_segment_macro_resolutions: RefCell<Vec<(Ident, MacroKind, ParentScope<'a>, - Option<&'a NameBinding<'a>>)>>, - multi_segment_macro_resolutions: RefCell<Vec<(Vec<Segment>, Span, MacroKind, ParentScope<'a>, - Option<Res>)>>, - builtin_attrs: RefCell<Vec<(Ident, ParentScope<'a>)>>, + // Mapping between names and their (possibly in-progress) resolutions in this module. + // Resolutions in modules from other crates are not populated until accessed. + lazy_resolutions: Resolutions<'a>, + // True if this is a module from other crate that needs to be populated on access. + populate_on_access: Cell<bool>, // Macro invocations that can expand into items in this module. - unresolved_invocations: RefCell<FxHashSet<ExpnId>>, + unexpanded_invocations: RefCell<FxHashSet<ExpnId>>, no_implicit_prelude: bool, @@ -435,11 +458,6 @@ pub struct ModuleData<'a> { // Used to memoize the traits in this module for faster searches through all traits in scope. traits: RefCell<Option<Box<[(Ident, &'a NameBinding<'a>)]>>>, - // Whether this module is populated. If not populated, any attempt to - // access the children must be preceded with a - // `populate_module_if_necessary` call. - populated: Cell<bool>, - /// Span of the module itself. Used for error reporting. span: Span, @@ -458,33 +476,34 @@ impl<'a> ModuleData<'a> { parent, kind, normal_ancestor_id, - resolutions: Default::default(), - single_segment_macro_resolutions: RefCell::new(Vec::new()), - multi_segment_macro_resolutions: RefCell::new(Vec::new()), - builtin_attrs: RefCell::new(Vec::new()), - unresolved_invocations: Default::default(), + lazy_resolutions: Default::default(), + populate_on_access: Cell::new(!normal_ancestor_id.is_local()), + unexpanded_invocations: Default::default(), no_implicit_prelude: false, glob_importers: RefCell::new(Vec::new()), globs: RefCell::new(Vec::new()), traits: RefCell::new(None), - populated: Cell::new(normal_ancestor_id.is_local()), span, expansion, } } - fn for_each_child<F: FnMut(Ident, Namespace, &'a NameBinding<'a>)>(&self, mut f: F) { - for (&(ident, ns), name_resolution) in self.resolutions.borrow().iter() { - name_resolution.borrow().binding.map(|binding| f(ident, ns, binding)); + fn for_each_child<R, F>(&'a self, resolver: &mut R, mut f: F) + where R: AsMut<Resolver<'a>>, F: FnMut(&mut R, Ident, Namespace, &'a NameBinding<'a>) + { + for (&(ident, ns), name_resolution) in resolver.as_mut().resolutions(self).borrow().iter() { + name_resolution.borrow().binding.map(|binding| f(resolver, ident, ns, binding)); } } - fn for_each_child_stable<F: FnMut(Ident, Namespace, &'a NameBinding<'a>)>(&self, mut f: F) { - let resolutions = self.resolutions.borrow(); + fn for_each_child_stable<R, F>(&'a self, resolver: &mut R, mut f: F) + where R: AsMut<Resolver<'a>>, F: FnMut(&mut R, Ident, Namespace, &'a NameBinding<'a>) + { + let resolutions = resolver.as_mut().resolutions(self).borrow(); let mut resolutions = resolutions.iter().collect::<Vec<_>>(); resolutions.sort_by_cached_key(|&(&(ident, ns), _)| (ident.as_str(), ns)); for &(&(ident, ns), &resolution) in resolutions.iter() { - resolution.borrow().binding.map(|binding| f(ident, ns, binding)); + resolution.borrow().binding.map(|binding| f(resolver, ident, ns, binding)); } } @@ -807,7 +826,7 @@ pub struct Resolver<'a> { pub definitions: Definitions, - graph_root: Module<'a>, + pub graph_root: Module<'a>, prelude: Option<Module<'a>>, pub extern_prelude: FxHashMap<Ident, ExternPreludeEntry<'a>>, @@ -896,15 +915,24 @@ pub struct Resolver<'a> { local_macro_def_scopes: FxHashMap<NodeId, Module<'a>>, unused_macros: NodeMap<Span>, proc_macro_stubs: NodeSet, + /// Traces collected during macro resolution and validated when it's complete. + single_segment_macro_resolutions: Vec<(Ident, MacroKind, ParentScope<'a>, + Option<&'a NameBinding<'a>>)>, + multi_segment_macro_resolutions: Vec<(Vec<Segment>, Span, MacroKind, ParentScope<'a>, + Option<Res>)>, + builtin_attrs: Vec<(Ident, ParentScope<'a>)>, /// Some built-in derives mark items they are applied to so they are treated specially later. /// Derive macros cannot modify the item themselves and have to store the markers in the global /// context, so they attach the markers to derive container IDs using this resolver table. /// FIXME: Find a way for `PartialEq` and `Eq` to emulate `#[structural_match]` /// by marking the produced impls rather than the original items. special_derives: FxHashMap<ExpnId, SpecialDerives>, - - /// Maps the `ExpnId` of an expansion to its containing module or block. - invocations: FxHashMap<ExpnId, &'a InvocationData<'a>>, + /// Parent scopes in which the macros were invoked. + /// FIXME: `derives` are missing in these parent scopes and need to be taken from elsewhere. + invocation_parent_scopes: FxHashMap<ExpnId, ParentScope<'a>>, + /// Legacy scopes *produced* by expanding the macro invocations, + /// include all the `macro_rules` items and other invocations generated by them. + output_legacy_scopes: FxHashMap<ExpnId, LegacyScope<'a>>, /// Avoid duplicated errors for "name already defined". name_already_seen: FxHashMap<Name, Span>, @@ -927,8 +955,8 @@ pub struct ResolverArenas<'a> { name_bindings: arena::TypedArena<NameBinding<'a>>, import_directives: arena::TypedArena<ImportDirective<'a>>, name_resolutions: arena::TypedArena<RefCell<NameResolution<'a>>>, - invocation_data: arena::TypedArena<InvocationData<'a>>, legacy_bindings: arena::TypedArena<LegacyBinding<'a>>, + ast_paths: arena::TypedArena<ast::Path>, } impl<'a> ResolverArenas<'a> { @@ -952,13 +980,16 @@ impl<'a> ResolverArenas<'a> { fn alloc_name_resolution(&'a self) -> &'a RefCell<NameResolution<'a>> { self.name_resolutions.alloc(Default::default()) } - fn alloc_invocation_data(&'a self, expansion_data: InvocationData<'a>) - -> &'a InvocationData<'a> { - self.invocation_data.alloc(expansion_data) - } fn alloc_legacy_binding(&'a self, binding: LegacyBinding<'a>) -> &'a LegacyBinding<'a> { self.legacy_bindings.alloc(binding) } + fn alloc_ast_paths(&'a self, paths: &[ast::Path]) -> &'a [ast::Path] { + self.ast_paths.alloc_from_iter(paths.iter().cloned()) + } +} + +impl<'a> AsMut<Resolver<'a>> for Resolver<'a> { + fn as_mut(&mut self) -> &mut Resolver<'a> { self } } impl<'a, 'b> ty::DefIdTree for &'a Resolver<'b> { @@ -985,11 +1016,11 @@ impl<'a> hir::lowering::Resolver for Resolver<'a> { } else { kw::Crate }; - let segments = iter::once(Ident::with_empty_ctxt(root)) + let segments = iter::once(Ident::with_dummy_span(root)) .chain( crate_root.into_iter() .chain(components.iter().cloned()) - .map(Ident::with_empty_ctxt) + .map(Ident::with_dummy_span) ).map(|i| self.new_ast_path_segment(i)).collect::<Vec<_>>(); let path = ast::Path { @@ -997,7 +1028,7 @@ impl<'a> hir::lowering::Resolver for Resolver<'a> { segments, }; - let parent_scope = &self.dummy_parent_scope(); + let parent_scope = &ParentScope::module(self.graph_root); let res = match self.resolve_ast_path(&path, ns, parent_scope) { Ok(res) => res, Err((span, error)) => { @@ -1060,18 +1091,17 @@ impl<'a> Resolver<'a> { .collect(); if !attr::contains_name(&krate.attrs, sym::no_core) { - extern_prelude.insert(Ident::with_empty_ctxt(sym::core), Default::default()); + extern_prelude.insert(Ident::with_dummy_span(sym::core), Default::default()); if !attr::contains_name(&krate.attrs, sym::no_std) { - extern_prelude.insert(Ident::with_empty_ctxt(sym::std), Default::default()); + extern_prelude.insert(Ident::with_dummy_span(sym::std), Default::default()); if session.rust_2018() { - extern_prelude.insert(Ident::with_empty_ctxt(sym::meta), Default::default()); + extern_prelude.insert(Ident::with_dummy_span(sym::meta), Default::default()); } } } - let mut invocations = FxHashMap::default(); - invocations.insert(ExpnId::root(), - arenas.alloc_invocation_data(InvocationData::root(graph_root))); + let mut invocation_parent_scopes = FxHashMap::default(); + invocation_parent_scopes.insert(ExpnId::root(), ParentScope::module(graph_root)); let mut macro_defs = FxHashMap::default(); macro_defs.insert(ExpnId::root(), root_def_id); @@ -1143,7 +1173,8 @@ impl<'a> Resolver<'a> { dummy_ext_bang: Lrc::new(SyntaxExtension::dummy_bang(session.edition())), dummy_ext_derive: Lrc::new(SyntaxExtension::dummy_derive(session.edition())), non_macro_attrs: [non_macro_attr(false), non_macro_attr(true)], - invocations, + invocation_parent_scopes, + output_legacy_scopes: Default::default(), macro_defs, local_macro_def_scopes: FxHashMap::default(), name_already_seen: FxHashMap::default(), @@ -1151,6 +1182,9 @@ impl<'a> Resolver<'a> { struct_constructors: Default::default(), unused_macros: Default::default(), proc_macro_stubs: Default::default(), + single_segment_macro_resolutions: Default::default(), + multi_segment_macro_resolutions: Default::default(), + builtin_attrs: Default::default(), special_derives: Default::default(), active_features: features.declared_lib_features.iter().map(|(feat, ..)| *feat) @@ -1182,9 +1216,8 @@ impl<'a> Resolver<'a> { f(self, MacroNS); } - fn is_builtin_macro(&mut self, def_id: Option<DefId>) -> bool { - def_id.and_then(|def_id| self.get_macro_by_def_id(def_id)) - .map_or(false, |ext| ext.is_builtin) + fn is_builtin_macro(&mut self, res: Res) -> bool { + self.get_macro(res).map_or(false, |ext| ext.is_builtin) } fn macro_def(&self, mut ctxt: SyntaxContext) -> DefId { @@ -1203,6 +1236,7 @@ impl<'a> Resolver<'a> { /// Entry point to crate resolution. pub fn resolve_crate(&mut self, krate: &Crate) { ImportResolver { r: self }.finalize_imports(); + self.finalize_macro_resolutions(); self.late_resolve_crate(krate); @@ -1223,6 +1257,20 @@ impl<'a> Resolver<'a> { self.arenas.alloc_module(module) } + fn resolutions(&mut self, module: Module<'a>) -> &'a Resolutions<'a> { + if module.populate_on_access.get() { + module.populate_on_access.set(false); + self.build_reduced_graph_external(module); + } + &module.lazy_resolutions + } + + fn resolution(&mut self, module: Module<'a>, ident: Ident, ns: Namespace) + -> &'a RefCell<NameResolution<'a>> { + *self.resolutions(module).borrow_mut().entry((ident.modern(), ns)) + .or_insert_with(|| self.arenas.alloc_name_resolution()) + } + fn record_use(&mut self, ident: Ident, ns: Namespace, used_binding: &'a NameBinding<'a>, is_lexical_scope: bool) { if let Some((b2, kind)) = used_binding.ambiguity { @@ -1319,13 +1367,15 @@ impl<'a> Resolver<'a> { ScopeSet::AbsolutePath(ns) => (ns, true), ScopeSet::Macro(_) => (MacroNS, false), }; + // Jump out of trait or enum modules, they do not act as scopes. + let module = parent_scope.module.nearest_item_scope(); let mut scope = match ns { _ if is_absolute_path => Scope::CrateRoot, - TypeNS | ValueNS => Scope::Module(parent_scope.module), + TypeNS | ValueNS => Scope::Module(module), MacroNS => Scope::DeriveHelpers, }; let mut ident = ident.modern(); - let mut use_prelude = !parent_scope.module.no_implicit_prelude; + let mut use_prelude = !module.no_implicit_prelude; loop { let visit = match scope { @@ -1355,10 +1405,11 @@ impl<'a> Resolver<'a> { LegacyScope::Binding(binding) => Scope::MacroRules( binding.parent_legacy_scope ), - LegacyScope::Invocation(invoc) => Scope::MacroRules( - invoc.output_legacy_scope.get().unwrap_or(invoc.parent_legacy_scope) + LegacyScope::Invocation(invoc_id) => Scope::MacroRules( + self.output_legacy_scopes.get(&invoc_id).cloned() + .unwrap_or(self.invocation_parent_scopes[&invoc_id].legacy) ), - LegacyScope::Empty => Scope::Module(parent_scope.module), + LegacyScope::Empty => Scope::Module(module), } Scope::CrateRoot => match ns { TypeNS => { @@ -1430,7 +1481,7 @@ impl<'a> Resolver<'a> { } let (general_span, modern_span) = if ident.name == kw::SelfUpper { // FIXME(jseyfried) improve `Self` hygiene - let empty_span = ident.span.with_ctxt(SyntaxContext::empty()); + let empty_span = ident.span.with_ctxt(SyntaxContext::root()); (empty_span, empty_span) } else if ns == TypeNS { let modern_span = ident.span.modern(); @@ -1448,7 +1499,7 @@ impl<'a> Resolver<'a> { debug!("walk rib\n{:?}", ribs[i].bindings); // Use the rib kind to determine whether we are resolving parameters // (modern hygiene) or local variables (legacy hygiene). - let rib_ident = if let AssocItemRibKind | ItemRibKind = ribs[i].kind { + let rib_ident = if ribs[i].kind.contains_params() { modern_ident } else { ident @@ -1501,7 +1552,7 @@ impl<'a> Resolver<'a> { self.hygienic_lexical_parent(module, &mut ident.span) }; module = unwrap_or!(opt_module, break); - let adjusted_parent_scope = &ParentScope { module, ..parent_scope.clone() }; + let adjusted_parent_scope = &ParentScope { module, ..*parent_scope }; let result = self.resolve_ident_in_module_unadjusted( ModuleOrUniformRoot::Module(module), ident, @@ -1637,7 +1688,7 @@ impl<'a> Resolver<'a> { ModuleOrUniformRoot::Module(m) => { if let Some(def) = ident.span.modernize_and_adjust(m.expansion) { tmp_parent_scope = - ParentScope { module: self.macro_def_scope(def), ..parent_scope.clone() }; + ParentScope { module: self.macro_def_scope(def), ..*parent_scope }; adjusted_parent_scope = &tmp_parent_scope; } } @@ -2606,7 +2657,6 @@ impl<'a> Resolver<'a> { return None; }; let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }); - self.populate_module_if_necessary(&crate_root); Some((crate_root, ty::Visibility::Public, DUMMY_SP, ExpnId::root()) .to_name_binding(self.arenas)) } @@ -2624,7 +2674,7 @@ impl<'a> Resolver<'a> { let path = if path_str.starts_with("::") { ast::Path { span, - segments: iter::once(Ident::with_empty_ctxt(kw::PathRoot)) + segments: iter::once(Ident::with_dummy_span(kw::PathRoot)) .chain({ path_str.split("::").skip(1).map(Ident::from_str) }) @@ -2645,7 +2695,7 @@ impl<'a> Resolver<'a> { let def_id = self.definitions.local_def_id(module_id); self.module_map.get(&def_id).copied().unwrap_or(self.graph_root) }); - let parent_scope = &ParentScope { module, ..self.dummy_parent_scope() }; + let parent_scope = &ParentScope::module(module); let res = self.resolve_ast_path(&path, ns, parent_scope).map_err(|_| ())?; Ok((path, res)) } @@ -2713,7 +2763,7 @@ fn module_to_string(module: Module<'_>) -> Option<String> { fn collect_mod(names: &mut Vec<Ident>, module: Module<'_>) { if let ModuleKind::Def(.., name) = module.kind { if let Some(parent) = module.parent { - names.push(Ident::with_empty_ctxt(name)); + names.push(Ident::with_dummy_span(name)); collect_mod(names, parent); } } else { diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 8e9e1380002..01ad67252a3 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -1,56 +1,32 @@ +//! A bunch of methods and structures more or less related to resolving macros and +//! interface provided by `Resolver` to macro expander. + use crate::{AmbiguityError, AmbiguityKind, AmbiguityErrorMisc, Determinacy}; use crate::{CrateLint, Resolver, ResolutionError, Scope, ScopeSet, ParentScope, Weak}; -use crate::{Module, ModuleKind, NameBinding, PathResult, Segment, ToNameBinding}; +use crate::{ModuleKind, NameBinding, PathResult, Segment, ToNameBinding}; use crate::{ModuleOrUniformRoot, KNOWN_TOOLS}; use crate::Namespace::*; -use crate::build_reduced_graph::BuildReducedGraphVisitor; use crate::resolve_imports::ImportResolver; use rustc::hir::def::{self, DefKind, NonMacroAttrKind}; -use rustc::hir::map::DefCollector; use rustc::middle::stability; use rustc::{ty, lint, span_bug}; -use syntax::ast::{self, Ident}; +use syntax::ast::{self, NodeId, Ident}; use syntax::attr::StabilityLevel; use syntax::edition::Edition; use syntax::ext::base::{self, Indeterminate, SpecialDerives}; use syntax::ext::base::{MacroKind, SyntaxExtension}; use syntax::ext::expand::{AstFragment, Invocation, InvocationKind}; -use syntax::ext::hygiene::{self, ExpnId, ExpnInfo, ExpnKind}; +use syntax::ext::hygiene::{self, ExpnId, ExpnData, ExpnKind}; use syntax::ext::tt::macro_rules; use syntax::feature_gate::{emit_feature_err, is_builtin_attr_name}; use syntax::feature_gate::GateIssue; use syntax::symbol::{Symbol, kw, sym}; use syntax_pos::{Span, DUMMY_SP}; -use std::cell::Cell; use std::{mem, ptr}; use rustc_data_structures::sync::Lrc; -type Res = def::Res<ast::NodeId>; - -// FIXME: Merge this with `ParentScope`. -#[derive(Clone, Debug)] -pub struct InvocationData<'a> { - /// The module in which the macro was invoked. - crate module: Module<'a>, - /// The legacy scope in which the macro was invoked. - /// The invocation path is resolved in this scope. - crate parent_legacy_scope: LegacyScope<'a>, - /// The legacy scope *produced* by expanding this macro invocation, - /// includes all the macro_rules items, other invocations, etc generated by it. - /// `None` if the macro is not expanded yet. - crate output_legacy_scope: Cell<Option<LegacyScope<'a>>>, -} - -impl<'a> InvocationData<'a> { - pub fn root(graph_root: Module<'a>) -> Self { - InvocationData { - module: graph_root, - parent_legacy_scope: LegacyScope::Empty, - output_legacy_scope: Cell::new(None), - } - } -} +type Res = def::Res<NodeId>; /// Binding produced by a `macro_rules` item. /// Not modularized, can shadow previous legacy bindings, etc. @@ -75,7 +51,7 @@ pub enum LegacyScope<'a> { Binding(&'a LegacyBinding<'a>), /// The scope introduced by a macro invocation that can potentially /// create a `macro_rules!` macro definition. - Invocation(&'a InvocationData<'a>), + Invocation(ExpnId), } // Macro namespace is separated into two sub-namespaces, one for bang macros and @@ -115,22 +91,17 @@ fn fast_print_path(path: &ast::Path) -> Symbol { } impl<'a> base::Resolver for Resolver<'a> { - fn next_node_id(&mut self) -> ast::NodeId { + fn next_node_id(&mut self) -> NodeId { self.session.next_node_id() } - fn get_module_scope(&mut self, id: ast::NodeId) -> ExpnId { - let span = DUMMY_SP.fresh_expansion(ExpnId::root(), ExpnInfo::default( + fn get_module_scope(&mut self, id: NodeId) -> ExpnId { + let expn_id = ExpnId::fresh(Some(ExpnData::default( ExpnKind::Macro(MacroKind::Attr, sym::test_case), DUMMY_SP, self.session.edition() - )); - let expn_id = span.ctxt().outer_expn(); + ))); let module = self.module_map[&self.definitions.local_def_id(id)]; + self.invocation_parent_scopes.insert(expn_id, ParentScope::module(module)); self.definitions.set_invocation_parent(expn_id, module.def_id().unwrap().index); - self.invocations.insert(expn_id, self.arenas.alloc_invocation_data(InvocationData { - module, - parent_legacy_scope: LegacyScope::Empty, - output_legacy_scope: Cell::new(None), - })); expn_id } @@ -144,29 +115,18 @@ impl<'a> base::Resolver for Resolver<'a> { }); } - fn visit_ast_fragment_with_placeholders(&mut self, expn_id: ExpnId, fragment: &AstFragment, - derives: &[ExpnId]) { - fragment.visit_with(&mut DefCollector::new(&mut self.definitions, expn_id)); - - let invocation = self.invocations[&expn_id]; - invocation.module.unresolved_invocations.borrow_mut().remove(&expn_id); - invocation.module.unresolved_invocations.borrow_mut().extend(derives); - let parent_def = self.definitions.invocation_parent(expn_id); - for &derive_invoc_id in derives { - self.definitions.set_invocation_parent(derive_invoc_id, parent_def); - } - self.invocations.extend(derives.iter().map(|&derive| (derive, invocation))); - let mut visitor = BuildReducedGraphVisitor { - r: self, - parent_scope: ParentScope { - module: invocation.module, - expansion: expn_id, - legacy: invocation.parent_legacy_scope, - derives: Vec::new(), - }, - }; - fragment.visit_with(&mut visitor); - invocation.output_legacy_scope.set(Some(visitor.parent_scope.legacy)); + // FIXME: `extra_placeholders` should be included into the `fragment` as regular placeholders. + fn visit_ast_fragment_with_placeholders( + &mut self, expansion: ExpnId, fragment: &AstFragment, extra_placeholders: &[NodeId] + ) { + // Integrate the new AST fragment into all the definition and module structures. + // We are inside the `expansion` now, but other parent scope components are still the same. + let parent_scope = ParentScope { expansion, ..self.invocation_parent_scopes[&expansion] }; + let output_legacy_scope = + self.build_reduced_graph(fragment, extra_placeholders, parent_scope); + self.output_legacy_scopes.insert(expansion, output_legacy_scope); + + parent_scope.module.unexpanded_invocations.borrow_mut().remove(&expansion); } fn register_builtin_macro(&mut self, ident: ast::Ident, ext: SyntaxExtension) { @@ -182,13 +142,14 @@ impl<'a> base::Resolver for Resolver<'a> { fn resolve_macro_invocation(&mut self, invoc: &Invocation, invoc_id: ExpnId, force: bool) -> Result<Option<Lrc<SyntaxExtension>>, Indeterminate> { - let (path, kind, derives_in_scope, after_derive) = match invoc.kind { + let parent_scope = self.invocation_parent_scopes[&invoc_id]; + let (path, kind, derives, after_derive) = match invoc.kind { InvocationKind::Attr { ref attr, ref derives, after_derive, .. } => - (&attr.path, MacroKind::Attr, derives.clone(), after_derive), + (&attr.path, MacroKind::Attr, self.arenas.alloc_ast_paths(derives), after_derive), InvocationKind::Bang { ref mac, .. } => - (&mac.node.path, MacroKind::Bang, Vec::new(), false), + (&mac.path, MacroKind::Bang, &[][..], false), InvocationKind::Derive { ref path, .. } => - (path, MacroKind::Derive, Vec::new(), false), + (path, MacroKind::Derive, &[][..], false), InvocationKind::DeriveContainer { ref derives, .. } => { // Block expansion of derives in the container until we know whether one of them // is a built-in `Copy`. Skip the resolution if there's only one derive - either @@ -196,10 +157,9 @@ impl<'a> base::Resolver for Resolver<'a> { // will automatically knows about itself. let mut result = Ok(None); if derives.len() > 1 { - let parent_scope = &self.invoc_parent_scope(invoc_id, Vec::new()); for path in derives { match self.resolve_macro_path(path, Some(MacroKind::Derive), - parent_scope, true, force) { + &parent_scope, true, force) { Ok((Some(ref ext), _)) if ext.is_derive_copy => { self.add_derives(invoc.expansion_data.id, SpecialDerives::COPY); return Ok(None); @@ -213,11 +173,14 @@ impl<'a> base::Resolver for Resolver<'a> { } }; - let parent_scope = &self.invoc_parent_scope(invoc_id, derives_in_scope); + // Derives are not included when `invocations` are collected, so we have to add them here. + let parent_scope = &ParentScope { derives, ..parent_scope }; let (ext, res) = self.smart_resolve_macro_path(path, kind, parent_scope, force)?; let span = invoc.span(); - invoc.expansion_data.id.set_expn_info(ext.expn_info(span, fast_print_path(path))); + invoc.expansion_data.id.set_expn_data( + ext.expn_data(parent_scope.expansion, span, fast_print_path(path)) + ); if let Res::Def(_, def_id) = res { if after_derive { @@ -251,20 +214,6 @@ impl<'a> base::Resolver for Resolver<'a> { } impl<'a> Resolver<'a> { - pub fn dummy_parent_scope(&self) -> ParentScope<'a> { - self.invoc_parent_scope(ExpnId::root(), Vec::new()) - } - - fn invoc_parent_scope(&self, invoc_id: ExpnId, derives: Vec<ast::Path>) -> ParentScope<'a> { - let invoc = self.invocations[&invoc_id]; - ParentScope { - module: invoc.module.nearest_item_scope(), - expansion: invoc_id.parent(), - legacy: invoc.parent_legacy_scope, - derives, - } - } - /// Resolve macro path with error reporting and recovery. fn smart_resolve_macro_path( &mut self, @@ -346,8 +295,7 @@ impl<'a> Resolver<'a> { // Possibly apply the macro helper hack if kind == Some(MacroKind::Bang) && path.len() == 1 && - path[0].ident.span.ctxt().outer_expn_info() - .map_or(false, |info| info.local_inner_macros) { + path[0].ident.span.ctxt().outer_expn_data().local_inner_macros { let root = Ident::new(kw::DollarCrate, path[0].ident.span); path.insert(0, Segment::from_ident(root)); } @@ -367,8 +315,8 @@ impl<'a> Resolver<'a> { if trace { let kind = kind.expect("macro kind must be specified if tracing is enabled"); - parent_scope.module.multi_segment_macro_resolutions.borrow_mut() - .push((path, path_span, kind, parent_scope.clone(), res.ok())); + self.multi_segment_macro_resolutions + .push((path, path_span, kind, *parent_scope, res.ok())); } self.prohibit_imported_non_macro_attrs(None, res.ok(), path_span); @@ -384,8 +332,8 @@ impl<'a> Resolver<'a> { if trace { let kind = kind.expect("macro kind must be specified if tracing is enabled"); - parent_scope.module.single_segment_macro_resolutions.borrow_mut() - .push((path[0].ident, kind, parent_scope.clone(), binding.ok())); + self.single_segment_macro_resolutions + .push((path[0].ident, kind, *parent_scope, binding.ok())); } let res = binding.map(|binding| binding.res()); @@ -454,8 +402,8 @@ impl<'a> Resolver<'a> { let result = match scope { Scope::DeriveHelpers => { let mut result = Err(Determinacy::Determined); - for derive in &parent_scope.derives { - let parent_scope = &ParentScope { derives: Vec::new(), ..*parent_scope }; + for derive in parent_scope.derives { + let parent_scope = &ParentScope { derives: &[], ..*parent_scope }; match this.resolve_macro_path(derive, Some(MacroKind::Derive), parent_scope, true, force) { Ok((Some(ext), _)) => if ext.helper_attrs.contains(&ident.name) { @@ -475,8 +423,9 @@ impl<'a> Resolver<'a> { Scope::MacroRules(legacy_scope) => match legacy_scope { LegacyScope::Binding(legacy_binding) if ident == legacy_binding.ident => Ok((legacy_binding.binding, Flags::MACRO_RULES)), - LegacyScope::Invocation(invoc) if invoc.output_legacy_scope.get().is_none() => - Err(Determinacy::Undetermined), + LegacyScope::Invocation(invoc_id) + if !this.output_legacy_scopes.contains_key(&invoc_id) => + Err(Determinacy::Undetermined), _ => Err(Determinacy::Determined), } Scope::CrateRoot => { @@ -500,7 +449,7 @@ impl<'a> Resolver<'a> { } } Scope::Module(module) => { - let adjusted_parent_scope = &ParentScope { module, ..parent_scope.clone() }; + let adjusted_parent_scope = &ParentScope { module, ..*parent_scope }; let binding = this.resolve_ident_in_module_unadjusted_ext( ModuleOrUniformRoot::Module(module), ident, @@ -531,7 +480,7 @@ impl<'a> Resolver<'a> { Scope::MacroUsePrelude => match this.macro_use_prelude.get(&ident.name).cloned() { Some(binding) => Ok((binding, Flags::PRELUDE | Flags::MISC_FROM_PRELUDE)), None => Err(Determinacy::determined( - this.graph_root.unresolved_invocations.borrow().is_empty() + this.graph_root.unexpanded_invocations.borrow().is_empty() )) } Scope::BuiltinAttrs => if is_builtin_attr_name(ident.name) { @@ -554,7 +503,7 @@ impl<'a> Resolver<'a> { Scope::ExternPrelude => match this.extern_prelude_get(ident, !record_used) { Some(binding) => Ok((binding, Flags::PRELUDE)), None => Err(Determinacy::determined( - this.graph_root.unresolved_invocations.borrow().is_empty() + this.graph_root.unexpanded_invocations.borrow().is_empty() )), } Scope::ToolPrelude => if KNOWN_TOOLS.contains(&ident.name) { @@ -575,7 +524,7 @@ impl<'a> Resolver<'a> { false, path_span, ) { - if use_prelude || this.is_builtin_macro(binding.res().opt_def_id()) { + if use_prelude || this.is_builtin_macro(binding.res()) { result = Ok((binding, Flags::PRELUDE | Flags::MISC_FROM_PRELUDE)); } } @@ -694,7 +643,7 @@ impl<'a> Resolver<'a> { } } - pub fn finalize_current_module_macro_resolutions(&mut self, module: Module<'a>) { + crate fn finalize_macro_resolutions(&mut self) { let check_consistency = |this: &mut Self, path: &[Segment], span, kind: MacroKind, initial_res: Option<Res>, res: Res| { if let Some(initial_res) = initial_res { @@ -730,8 +679,7 @@ impl<'a> Resolver<'a> { } }; - let macro_resolutions = - mem::take(&mut *module.multi_segment_macro_resolutions.borrow_mut()); + let macro_resolutions = mem::take(&mut self.multi_segment_macro_resolutions); for (mut path, path_span, kind, parent_scope, initial_res) in macro_resolutions { // FIXME: Path resolution will ICE if segment IDs present. for seg in &mut path { seg.id = None; } @@ -758,8 +706,7 @@ impl<'a> Resolver<'a> { } } - let macro_resolutions = - mem::take(&mut *module.single_segment_macro_resolutions.borrow_mut()); + let macro_resolutions = mem::take(&mut self.single_segment_macro_resolutions); for (ident, kind, parent_scope, initial_binding) in macro_resolutions { match self.early_resolve_ident_in_lexical_scope(ident, ScopeSet::Macro(kind), &parent_scope, true, true, ident.span) { @@ -784,7 +731,7 @@ impl<'a> Resolver<'a> { } } - let builtin_attrs = mem::take(&mut *module.builtin_attrs.borrow_mut()); + let builtin_attrs = mem::take(&mut self.builtin_attrs); for (ident, parent_scope) in builtin_attrs { let _ = self.early_resolve_ident_in_lexical_scope( ident, ScopeSet::Macro(MacroKind::Attr), &parent_scope, true, true, ident.span diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 00e89f0fdae..fd222a132a3 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -1,3 +1,5 @@ +//! A bunch of methods and structures more or less related to resolving imports. + use ImportDirectiveSubclass::*; use crate::{AmbiguityError, AmbiguityKind, AmbiguityErrorMisc}; @@ -5,9 +7,8 @@ use crate::{CrateLint, Module, ModuleOrUniformRoot, PerNS, ScopeSet, ParentScope use crate::Determinacy::{self, *}; use crate::Namespace::{self, TypeNS, MacroNS}; use crate::{NameBinding, NameBindingKind, ToNameBinding, PathResult, PrivacyError}; -use crate::{Resolver, ResolutionError, Segment}; +use crate::{Resolver, ResolutionError, Segment, ModuleKind}; use crate::{names_to_string, module_to_string}; -use crate::ModuleKind; use crate::diagnostics::Suggestion; use errors::Applicability; @@ -35,7 +36,7 @@ use syntax_pos::{MultiSpan, Span}; use log::*; -use std::cell::{Cell, RefCell}; +use std::cell::Cell; use std::{mem, ptr}; type Res = def::Res<NodeId>; @@ -159,12 +160,6 @@ impl<'a> NameResolution<'a> { } impl<'a> Resolver<'a> { - crate fn resolution(&self, module: Module<'a>, ident: Ident, ns: Namespace) - -> &'a RefCell<NameResolution<'a>> { - *module.resolutions.borrow_mut().entry((ident.modern(), ns)) - .or_insert_with(|| self.arenas.alloc_name_resolution()) - } - crate fn resolve_ident_in_module_unadjusted( &mut self, module: ModuleOrUniformRoot<'a>, @@ -207,7 +202,7 @@ impl<'a> Resolver<'a> { Err((Determined, Weak::No)) } else if let Some(binding) = self.extern_prelude_get(ident, !record_used) { Ok(binding) - } else if !self.graph_root.unresolved_invocations.borrow().is_empty() { + } else if !self.graph_root.unexpanded_invocations.borrow().is_empty() { // Macro-expanded `extern crate` items can add names to extern prelude. Err((Undetermined, Weak::No)) } else { @@ -240,8 +235,6 @@ impl<'a> Resolver<'a> { } }; - self.populate_module_if_necessary(module); - let resolution = self.resolution(module, ident, ns) .try_borrow_mut() .map_err(|_| (Determined, Weak::No))?; // This happens when there is a cycle of imports. @@ -355,7 +348,7 @@ impl<'a> Resolver<'a> { // progress, we have to ignore those potential unresolved invocations from other modules // and prohibit access to macro-expanded `macro_export` macros instead (unless restricted // shadowing is enabled, see `macro_expanded_macro_export_errors`). - let unexpanded_macros = !module.unresolved_invocations.borrow().is_empty(); + let unexpanded_macros = !module.unexpanded_invocations.borrow().is_empty(); if let Some(binding) = resolution.binding { if !unexpanded_macros || ns == MacroNS || restricted_shadowing { return check_usable(self, binding); @@ -394,7 +387,7 @@ impl<'a> Resolver<'a> { match ident.span.glob_adjust(module.expansion, glob_import.span) { Some(Some(def)) => { tmp_parent_scope = - ParentScope { module: self.macro_def_scope(def), ..parent_scope.clone() }; + ParentScope { module: self.macro_def_scope(def), ..*parent_scope }; adjusted_parent_scope = &tmp_parent_scope; } Some(None) => {} @@ -848,7 +841,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { directive.vis.set(orig_vis); let module = match path_res { PathResult::Module(module) => { - // Consistency checks, analogous to `finalize_current_module_macro_resolutions`. + // Consistency checks, analogous to `finalize_macro_resolutions`. if let Some(initial_module) = directive.imported_module.get() { if !ModuleOrUniformRoot::same_def(module, initial_module) && no_ambiguity { span_bug!(directive.span, "inconsistent resolution for an import"); @@ -973,7 +966,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { match binding { Ok(binding) => { - // Consistency checks, analogous to `finalize_current_module_macro_resolutions`. + // Consistency checks, analogous to `finalize_macro_resolutions`. let initial_res = source_bindings[ns].get().map(|initial_binding| { all_ns_err = false; if let Some(target_binding) = target_bindings[ns].get() { @@ -1025,7 +1018,8 @@ impl<'a, 'b> ImportResolver<'a, 'b> { return if all_ns_failed { let resolutions = match module { - ModuleOrUniformRoot::Module(module) => Some(module.resolutions.borrow()), + ModuleOrUniformRoot::Module(module) => + Some(self.r.resolutions(module).borrow()), _ => None, }; let resolutions = resolutions.as_ref().into_iter().flat_map(|r| r.iter()); @@ -1263,8 +1257,6 @@ impl<'a, 'b> ImportResolver<'a, 'b> { } }; - self.r.populate_module_if_necessary(module); - if module.is_trait() { self.r.session.span_err(directive.span, "items in traits are not importable."); return; @@ -1280,8 +1272,8 @@ impl<'a, 'b> ImportResolver<'a, 'b> { // Ensure that `resolutions` isn't borrowed during `try_define`, // since it might get updated via a glob cycle. - let bindings = module.resolutions.borrow().iter().filter_map(|(&ident, resolution)| { - resolution.borrow().binding().map(|binding| (ident, binding)) + let bindings = self.r.resolutions(module).borrow().iter().filter_map(|(ident, resolution)| { + resolution.borrow().binding().map(|binding| (*ident, binding)) }).collect::<Vec<_>>(); for ((mut ident, ns), binding) in bindings { let scope = match ident.span.reverse_glob_adjust(module.expansion, directive.span) { @@ -1308,7 +1300,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { let mut reexports = Vec::new(); - for (&(ident, ns), resolution) in module.resolutions.borrow().iter() { + for (&(ident, ns), resolution) in self.r.resolutions(module).borrow().iter() { let resolution = &mut *resolution.borrow_mut(); let binding = match resolution.binding { Some(binding) => binding, @@ -1367,8 +1359,8 @@ impl<'a, 'b> ImportResolver<'a, 'b> { Some(ModuleOrUniformRoot::Module(module)) => module, _ => bug!("module should exist"), }; - let resolutions = imported_module.parent.expect("parent should exist") - .resolutions.borrow(); + let parent_module = imported_module.parent.expect("parent should exist"); + let resolutions = self.r.resolutions(parent_module).borrow(); let enum_path_segment_index = directive.module_path.len() - 1; let enum_ident = directive.module_path[enum_path_segment_index].ident; diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index c32d4885c4a..9068605b075 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -32,7 +32,7 @@ use syntax::print::pprust::{ ty_to_string }; use syntax::ptr::P; -use syntax::source_map::{Spanned, DUMMY_SP, respan}; +use syntax::source_map::{DUMMY_SP, respan}; use syntax::walk_list; use syntax_pos::*; @@ -557,11 +557,11 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { let access = access_from!(self.save_ctxt, item, hir_id); for variant in &enum_definition.variants { - let name = variant.node.ident.name.to_string(); + let name = variant.ident.name.to_string(); let qualname = format!("{}::{}", enum_data.qualname, name); - let name_span = variant.node.ident.span; + let name_span = variant.ident.span; - match variant.node.data { + match variant.data { ast::VariantData::Struct(ref fields, ..) => { let fields_str = fields .iter() @@ -574,7 +574,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { let value = format!("{}::{} {{ {} }}", enum_data.name, name, fields_str); if !self.span.filter_generated(name_span) { let span = self.span_from_span(name_span); - let id = id_from_node_id(variant.node.id, &self.save_ctxt); + let id = id_from_node_id(variant.id, &self.save_ctxt); let parent = Some(id_from_node_id(item.id, &self.save_ctxt)); self.dumper.dump_def( @@ -589,10 +589,10 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { parent, children: vec![], decl_id: None, - docs: self.save_ctxt.docs_for_attrs(&variant.node.attrs), + docs: self.save_ctxt.docs_for_attrs(&variant.attrs), sig: sig::variant_signature(variant, &self.save_ctxt), attributes: lower_attributes( - variant.node.attrs.clone(), + variant.attrs.clone(), &self.save_ctxt, ), }, @@ -612,7 +612,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { } if !self.span.filter_generated(name_span) { let span = self.span_from_span(name_span); - let id = id_from_node_id(variant.node.id, &self.save_ctxt); + let id = id_from_node_id(variant.id, &self.save_ctxt); let parent = Some(id_from_node_id(item.id, &self.save_ctxt)); self.dumper.dump_def( @@ -627,10 +627,10 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { parent, children: vec![], decl_id: None, - docs: self.save_ctxt.docs_for_attrs(&variant.node.attrs), + docs: self.save_ctxt.docs_for_attrs(&variant.attrs), sig: sig::variant_signature(variant, &self.save_ctxt), attributes: lower_attributes( - variant.node.attrs.clone(), + variant.attrs.clone(), &self.save_ctxt, ), }, @@ -640,8 +640,8 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { } - for field in variant.node.data.fields() { - self.process_struct_field_def(field, variant.node.id); + for field in variant.data.fields() { + self.process_struct_field_def(field, variant.id); self.visit_ty(&field.ty); } } @@ -879,7 +879,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { }; let variant = adt.variant_of_res(self.save_ctxt.get_path_res(p.id)); - for &Spanned { node: ref field, .. } in fields { + for field in fields { if let Some(index) = self.tcx.find_field_index(field.ident, variant) { if !self.span.filter_generated(field.ident.span) { let span = self.span_from_span(field.ident.span); diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index c699a8834e0..0bbbbb8249c 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -277,7 +277,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { filter!(self.span_utils, item.ident.span); let variants_str = def.variants .iter() - .map(|v| v.node.ident.to_string()) + .map(|v| v.ident.to_string()) .collect::<Vec<_>>() .join(", "); let value = format!("{}::{{{}}}", name, variants_str); @@ -291,7 +291,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { parent: None, children: def.variants .iter() - .map(|v| id_from_node_id(v.node.id, self)) + .map(|v| id_from_node_id(v.id, self)) .collect(), decl_id: None, docs: self.docs_for_attrs(&item.attrs), @@ -1156,7 +1156,7 @@ fn escape(s: String) -> String { // Helper function to determine if a span came from a // macro expansion or syntax extension. fn generated_code(span: Span) -> bool { - span.ctxt() != NO_EXPANSION || span.is_dummy() + span.from_expansion() || span.is_dummy() } // DefId::index is a newtype and so the JSON serialisation is ugly. Therefore diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index c212cda2d66..b34506a4f1d 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -65,7 +65,7 @@ pub fn variant_signature(variant: &ast::Variant, scx: &SaveContext<'_, '_>) -> O if !scx.config.signatures { return None; } - variant.node.make(0, None, scx).ok() + variant.make(0, None, scx).ok() } pub fn method_signature( @@ -699,7 +699,7 @@ impl Sig for ast::StructField { } -impl Sig for ast::Variant_ { +impl Sig for ast::Variant { fn make(&self, offset: usize, parent_id: Option<NodeId>, scx: &SaveContext<'_, '_>) -> Result { let mut text = self.ident.to_string(); match self.data { diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index dd7ae742a63..dafa8661176 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -114,26 +114,20 @@ impl TargetDataLayout { [p] if p.starts_with("P") => { dl.instruction_address_space = parse_address_space(&p[1..], "P")? } - // FIXME: Ping cfg(bootstrap) -- Use `ref a @ ..` with new bootstrap compiler. - ["a", ..] => { - let a = &spec_parts[1..]; // FIXME inline into pattern. + ["a", ref a @ ..] => { dl.aggregate_align = align(a, "a")? } - ["f32", ..] => { - let a = &spec_parts[1..]; // FIXME inline into pattern. + ["f32", ref a @ ..] => { dl.f32_align = align(a, "f32")? } - ["f64", ..] => { - let a = &spec_parts[1..]; // FIXME inline into pattern. + ["f64", ref a @ ..] => { dl.f64_align = align(a, "f64")? } - [p @ "p", s, ..] | [p @ "p0", s, ..] => { - let a = &spec_parts[2..]; // FIXME inline into pattern. + [p @ "p", s, ref a @ ..] | [p @ "p0", s, ref a @ ..] => { dl.pointer_size = size(s, p)?; dl.pointer_align = align(a, p)?; } - [s, ..] if s.starts_with("i") => { - let a = &spec_parts[1..]; // FIXME inline into pattern. + [s, ref a @ ..] if s.starts_with("i") => { let bits = match s[1..].parse::<u64>() { Ok(bits) => bits, Err(_) => { @@ -157,8 +151,7 @@ impl TargetDataLayout { dl.i128_align = a; } } - [s, ..] if s.starts_with("v") => { - let a = &spec_parts[1..]; // FIXME inline into pattern. + [s, ref a @ ..] if s.starts_with("v") => { let v_size = size(&s[1..], "v")?; let a = align(a, s)?; if let Some(v) = dl.vector_align.iter_mut().find(|v| v.0 == v_size) { diff --git a/src/librustc_target/spec/aarch64_uwp_windows_msvc.rs b/src/librustc_target/spec/aarch64_uwp_windows_msvc.rs new file mode 100644 index 00000000000..5d8b829f2ab --- /dev/null +++ b/src/librustc_target/spec/aarch64_uwp_windows_msvc.rs @@ -0,0 +1,24 @@ +use crate::spec::{LinkerFlavor, Target, TargetResult, PanicStrategy}; + +pub fn target() -> TargetResult { + let mut base = super::windows_uwp_msvc_base::opts(); + base.max_atomic_width = Some(64); + base.has_elf_tls = true; + + // FIXME: this shouldn't be panic=abort, it should be panic=unwind + base.panic_strategy = PanicStrategy::Abort; + + Ok(Target { + llvm_target: "aarch64-pc-windows-msvc".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "64".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128".to_string(), + arch: "aarch64".to_string(), + target_os: "windows".to_string(), + target_env: "msvc".to_string(), + target_vendor: "uwp".to_string(), + linker_flavor: LinkerFlavor::Msvc, + options: base, + }) +} diff --git a/src/librustc_target/spec/apple_ios_base.rs b/src/librustc_target/spec/apple_ios_base.rs index f46ad06ba43..6d3900c0b20 100644 --- a/src/librustc_target/spec/apple_ios_base.rs +++ b/src/librustc_target/spec/apple_ios_base.rs @@ -13,7 +13,8 @@ pub enum Arch { Armv7s, Arm64, I386, - X86_64 + X86_64, + X86_64_macabi, } impl Arch { @@ -23,7 +24,8 @@ impl Arch { Armv7s => "armv7s", Arm64 => "arm64", I386 => "i386", - X86_64 => "x86_64" + X86_64 => "x86_64", + X86_64_macabi => "x86_64" } } } @@ -67,7 +69,8 @@ pub fn get_sdk_root(sdk_name: &str) -> Result<String, String> { fn build_pre_link_args(arch: Arch) -> Result<LinkArgs, String> { let sdk_name = match arch { Armv7 | Armv7s | Arm64 => "iphoneos", - I386 | X86_64 => "iphonesimulator" + I386 | X86_64 => "iphonesimulator", + X86_64_macabi => "macosx10.15", }; let arch_name = arch.to_string(); @@ -93,6 +96,7 @@ fn target_cpu(arch: Arch) -> String { Arm64 => "cyclone", I386 => "yonah", X86_64 => "core2", + X86_64_macabi => "core2", }.to_string() } diff --git a/src/librustc_target/spec/i686_uwp_windows_msvc.rs b/src/librustc_target/spec/i686_uwp_windows_msvc.rs new file mode 100644 index 00000000000..5e8e8c2a414 --- /dev/null +++ b/src/librustc_target/spec/i686_uwp_windows_msvc.rs @@ -0,0 +1,22 @@ +use crate::spec::{LinkerFlavor, Target, TargetResult}; + +pub fn target() -> TargetResult { + let mut base = super::windows_uwp_msvc_base::opts(); + base.cpu = "pentium4".to_string(); + base.max_atomic_width = Some(64); + base.has_elf_tls = true; + + Ok(Target { + llvm_target: "i686-pc-windows-msvc".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "32".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32".to_string(), + arch: "x86".to_string(), + target_os: "windows".to_string(), + target_env: "msvc".to_string(), + target_vendor: "uwp".to_string(), + linker_flavor: LinkerFlavor::Msvc, + options: base, + }) +} diff --git a/src/librustc_target/spec/mips64_unknown_linux_muslabi64.rs b/src/librustc_target/spec/mips64_unknown_linux_muslabi64.rs new file mode 100644 index 00000000000..75f3efa49c4 --- /dev/null +++ b/src/librustc_target/spec/mips64_unknown_linux_muslabi64.rs @@ -0,0 +1,25 @@ +use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; + +pub fn target() -> TargetResult { + let mut base = super::linux_musl_base::opts(); + base.cpu = "mips64r2".to_string(); + base.features = "+mips64r2".to_string(); + base.max_atomic_width = Some(64); + Ok(Target { + // LLVM doesn't recognize "muslabi64" yet. + llvm_target: "mips64-unknown-linux-musl".to_string(), + target_endian: "big".to_string(), + target_pointer_width: "64".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".to_string(), + arch: "mips64".to_string(), + target_os: "linux".to_string(), + target_env: "musl".to_string(), + target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, + options: TargetOptions { + target_mcount: "_mcount".to_string(), + .. base + }, + }) +} diff --git a/src/librustc_target/spec/mips64el_unknown_linux_muslabi64.rs b/src/librustc_target/spec/mips64el_unknown_linux_muslabi64.rs new file mode 100644 index 00000000000..a6aad3ddd3d --- /dev/null +++ b/src/librustc_target/spec/mips64el_unknown_linux_muslabi64.rs @@ -0,0 +1,25 @@ +use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; + +pub fn target() -> TargetResult { + let mut base = super::linux_musl_base::opts(); + base.cpu = "mips64r2".to_string(); + base.features = "+mips64r2".to_string(); + base.max_atomic_width = Some(64); + Ok(Target { + // LLVM doesn't recognize "muslabi64" yet. + llvm_target: "mips64el-unknown-linux-musl".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "64".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".to_string(), + arch: "mips64".to_string(), + target_os: "linux".to_string(), + target_env: "musl".to_string(), + target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, + options: TargetOptions { + target_mcount: "_mcount".to_string(), + .. base + }, + }) +} diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index aed31bd2fb2..539e28f7088 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -61,6 +61,7 @@ mod uefi_base; mod windows_base; mod windows_msvc_base; mod windows_uwp_base; +mod windows_uwp_msvc_base; mod thumb_base; mod l4re_base; mod fuchsia_base; @@ -371,6 +372,8 @@ supported_targets! { ("i586-unknown-linux-musl", i586_unknown_linux_musl), ("mips-unknown-linux-musl", mips_unknown_linux_musl), ("mipsel-unknown-linux-musl", mipsel_unknown_linux_musl), + ("mips64-unknown-linux-muslabi64", mips64_unknown_linux_muslabi64), + ("mips64el-unknown-linux-muslabi64", mips64el_unknown_linux_muslabi64), ("hexagon-unknown-linux-musl", hexagon_unknown_linux_musl), ("mips-unknown-linux-uclibc", mips_unknown_linux_uclibc), @@ -395,6 +398,7 @@ supported_targets! { ("aarch64-unknown-openbsd", aarch64_unknown_openbsd), ("i686-unknown-openbsd", i686_unknown_openbsd), + ("sparc64-unknown-openbsd", sparc64_unknown_openbsd), ("x86_64-unknown-openbsd", x86_64_unknown_openbsd), ("aarch64-unknown-netbsd", aarch64_unknown_netbsd), @@ -425,6 +429,7 @@ supported_targets! { ("aarch64-apple-ios", aarch64_apple_ios), ("armv7-apple-ios", armv7_apple_ios), ("armv7s-apple-ios", armv7s_apple_ios), + ("x86_64-apple-ios-macabi", x86_64_apple_ios_macabi), ("armebv7r-none-eabi", armebv7r_none_eabi), ("armebv7r-none-eabihf", armebv7r_none_eabihf), @@ -442,8 +447,11 @@ supported_targets! { ("x86_64-uwp-windows-gnu", x86_64_uwp_windows_gnu), ("aarch64-pc-windows-msvc", aarch64_pc_windows_msvc), + ("aarch64-uwp-windows-msvc", aarch64_uwp_windows_msvc), ("x86_64-pc-windows-msvc", x86_64_pc_windows_msvc), + ("x86_64-uwp-windows-msvc", x86_64_uwp_windows_msvc), ("i686-pc-windows-msvc", i686_pc_windows_msvc), + ("i686-uwp-windows-msvc", i686_uwp_windows_msvc), ("i586-pc-windows-msvc", i586_pc_windows_msvc), ("thumbv7a-pc-windows-msvc", thumbv7a_pc_windows_msvc), diff --git a/src/librustc_target/spec/sparc64_unknown_openbsd.rs b/src/librustc_target/spec/sparc64_unknown_openbsd.rs new file mode 100644 index 00000000000..229e0621e0d --- /dev/null +++ b/src/librustc_target/spec/sparc64_unknown_openbsd.rs @@ -0,0 +1,22 @@ +use crate::spec::{LinkerFlavor, Target, TargetResult}; + +pub fn target() -> TargetResult { + let mut base = super::openbsd_base::opts(); + base.cpu = "v9".to_string(); + base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.max_atomic_width = Some(64); + + Ok(Target { + llvm_target: "sparc64-unknown-openbsd".to_string(), + target_endian: "big".to_string(), + target_pointer_width: "64".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "E-m:e-i64:64-n32:64-S128".to_string(), + arch: "sparc64".to_string(), + target_os: "openbsd".to_string(), + target_env: String::new(), + target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, + options: base, + }) +} diff --git a/src/librustc_target/spec/windows_uwp_msvc_base.rs b/src/librustc_target/spec/windows_uwp_msvc_base.rs new file mode 100644 index 00000000000..1121916e68f --- /dev/null +++ b/src/librustc_target/spec/windows_uwp_msvc_base.rs @@ -0,0 +1,33 @@ +use crate::spec::{LinkArgs, LinkerFlavor, TargetOptions}; +use std::default::Default; + +pub fn opts() -> TargetOptions { + let mut args = LinkArgs::new(); + args.insert(LinkerFlavor::Msvc, + vec!["/NOLOGO".to_string(), + "/NXCOMPAT".to_string(), + "/APPCONTAINER".to_string(), + "mincore.lib".to_string()]); + + TargetOptions { + function_sections: true, + dynamic_linking: true, + executables: true, + dll_prefix: String::new(), + dll_suffix: ".dll".to_string(), + exe_suffix: ".exe".to_string(), + staticlib_prefix: String::new(), + staticlib_suffix: ".lib".to_string(), + target_family: Some("windows".to_string()), + is_like_windows: true, + is_like_msvc: true, + pre_link_args: args, + crt_static_allows_dylibs: true, + crt_static_respected: true, + abi_return_struct_as_int: true, + emit_debug_gdb_scripts: false, + requires_uwtable: true, + + .. Default::default() + } +} diff --git a/src/librustc_target/spec/x86_64_apple_ios_macabi.rs b/src/librustc_target/spec/x86_64_apple_ios_macabi.rs new file mode 100644 index 00000000000..2ce77282e90 --- /dev/null +++ b/src/librustc_target/spec/x86_64_apple_ios_macabi.rs @@ -0,0 +1,23 @@ +use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; +use super::apple_ios_base::{opts, Arch}; + +pub fn target() -> TargetResult { + let base = opts(Arch::X86_64_macabi)?; + Ok(Target { + llvm_target: "x86_64-apple-ios13.0-macabi".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "64".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "e-m:o-i64:64-f80:128-n8:16:32:64-S128".to_string(), + arch: "x86_64".to_string(), + target_os: "ios".to_string(), + target_env: String::new(), + target_vendor: "apple".to_string(), + linker_flavor: LinkerFlavor::Gcc, + options: TargetOptions { + max_atomic_width: Some(64), + stack_probes: true, + .. base + } + }) +} diff --git a/src/librustc_target/spec/x86_64_uwp_windows_msvc.rs b/src/librustc_target/spec/x86_64_uwp_windows_msvc.rs new file mode 100644 index 00000000000..40dd52c1591 --- /dev/null +++ b/src/librustc_target/spec/x86_64_uwp_windows_msvc.rs @@ -0,0 +1,22 @@ +use crate::spec::{LinkerFlavor, Target, TargetResult}; + +pub fn target() -> TargetResult { + let mut base = super::windows_uwp_msvc_base::opts(); + base.cpu = "x86-64".to_string(); + base.max_atomic_width = Some(64); + base.has_elf_tls = true; + + Ok(Target { + llvm_target: "x86_64-pc-windows-msvc".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "64".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "e-m:w-i64:64-f80:128-n8:16:32:64-S128".to_string(), + arch: "x86_64".to_string(), + target_os: "windows".to_string(), + target_env: "msvc".to_string(), + target_vendor: "uwp".to_string(), + linker_flavor: LinkerFlavor::Msvc, + options: base, + }) +} diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 922afbae2a4..9e52eae88ef 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -635,8 +635,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }); let default_needs_object_self = |param: &ty::GenericParamDef| { if let GenericParamDefKind::Type { has_default, .. } = param.kind { - if is_object && has_default { - if tcx.at(span).type_of(param.def_id).has_self_ty() { + if is_object && has_default && has_self { + let self_param = tcx.types.self_param; + if tcx.at(span).type_of(param.def_id).walk().any(|ty| ty == self_param) { // There is no suitable inference default for a type parameter // that references self, in an object type. return true; @@ -2030,7 +2031,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // `Self` in trait or type alias. assert_eq!(opt_self_ty, None); self.prohibit_generics(&path.segments); - tcx.mk_self_type() + tcx.types.self_param } Res::SelfTy(_, Some(def_id)) => { // `Self` in impl (we know the concrete type). diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 3a43e764dd0..fc25eb44cbd 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -12,7 +12,6 @@ use rustc::traits::{ObligationCause, ObligationCauseCode}; use rustc::ty::{self, Ty, TypeFoldable}; use rustc::ty::subst::Kind; use syntax::ast; -use syntax::source_map::Spanned; use syntax::util::lev_distance::find_best_match_for_name; use syntax_pos::Span; use syntax_pos::hygiene::DesugaringKind; @@ -54,6 +53,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let is_non_ref_pat = match pat.node { PatKind::Struct(..) | PatKind::TupleStruct(..) | + PatKind::Or(_) | PatKind::Tuple(..) | PatKind::Box(_) | PatKind::Range(..) | @@ -310,6 +310,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { PatKind::Struct(ref qpath, ref fields, etc) => { self.check_pat_struct(pat, qpath, fields, etc, expected, def_bm, discrim_span) } + PatKind::Or(ref pats) => { + let expected_ty = self.structurally_resolved_type(pat.span, expected); + for pat in pats { + self.check_pat_walk(pat, expected, def_bm, discrim_span); + } + expected_ty + } PatKind::Tuple(ref elements, ddpos) => { let mut expected_len = elements.len(); if ddpos.is_some() { @@ -1036,7 +1043,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); &self, pat: &'tcx hir::Pat, qpath: &hir::QPath, - fields: &'tcx [Spanned<hir::FieldPat>], + fields: &'tcx [hir::FieldPat], etc: bool, expected: Ty<'tcx>, def_bm: ty::BindingMode, @@ -1048,7 +1055,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); variant_ty } else { for field in fields { - self.check_pat_walk(&field.node.pat, self.tcx.types.err, def_bm, discrim_span); + self.check_pat_walk(&field.pat, self.tcx.types.err, def_bm, discrim_span); } return self.tcx.types.err; }; @@ -1206,7 +1213,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); pat_id: hir::HirId, span: Span, variant: &'tcx ty::VariantDef, - fields: &'tcx [Spanned<hir::FieldPat>], + fields: &'tcx [hir::FieldPat], etc: bool, def_bm: ty::BindingMode, ) -> bool { @@ -1231,7 +1238,8 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); let mut inexistent_fields = vec![]; // Typecheck each field. - for &Spanned { node: ref field, span } in fields { + for field in fields { + let span = field.span; let ident = tcx.adjust_ident(field.ident, variant.def_id); let field_ty = match used_fields.entry(ident) { Occupied(occupied) => { diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 946082746f4..8e187b7e05b 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -518,7 +518,7 @@ fn compare_self_type<'tcx>( let self_string = |method: &ty::AssocItem| { let untransformed_self_ty = match method.container { ty::ImplContainer(_) => impl_trait_ref.self_ty(), - ty::TraitContainer(_) => tcx.mk_self_type() + ty::TraitContainer(_) => tcx.types.self_param }; let self_arg_ty = *tcx.fn_sig(method.def_id).input(0).skip_binder(); let param_env = ty::ParamEnv::reveal_all(); diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 3229d49841e..de5ba8bc8eb 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -127,6 +127,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.suggest_compatible_variants(&mut err, expr, expected, expr_ty); self.suggest_ref_or_into(&mut err, expr, expected, expr_ty); + self.suggest_boxing_when_appropriate(&mut err, expr, expected, expr_ty); self.suggest_missing_await(&mut err, expr, expected, expr_ty); (expected, Some(err)) @@ -346,9 +347,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { sp, ); - // Check the `expn_info()` to see if this is a macro; if so, it's hard to - // extract the text and make a good suggestion, so don't bother. - let is_macro = sp.ctxt().outer_expn_info().is_some(); + // If the span is from a macro, then it's hard to extract the text + // and make a good suggestion, so don't bother. + let is_macro = sp.from_expansion(); match (&expr.node, &expected.sty, &checked_ty.sty) { (_, &ty::Ref(_, exp, _), &ty::Ref(_, check, _)) => match (&exp.sty, &check.sty) { @@ -548,11 +549,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { checked_ty: Ty<'tcx>, expected_ty: Ty<'tcx>, ) -> bool { - if self.tcx.hir().is_const_scope(expr.hir_id) { + if self.tcx.hir().is_const_context(expr.hir_id) { // Shouldn't suggest `.into()` on `const`s. // FIXME(estebank): modify once we decide to suggest `as` casts return false; } + if !self.tcx.sess.source_map().span_to_filename(expr.span).is_real() { + // Ignore if span is from within a macro. + return false; + } // If casting this expression to a given numeric type would be appropriate in case of a type // mismatch. diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index 9680f61d699..d139cd4264c 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -24,6 +24,7 @@ use syntax::source_map::Span; use syntax::util::lev_distance::find_best_match_for_name; use rustc::hir; use rustc::hir::{ExprKind, QPath}; +use rustc::hir::def_id::DefId; use rustc::hir::def::{CtorKind, Res, DefKind}; use rustc::hir::ptr::P; use rustc::infer; @@ -1336,116 +1337,182 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { autoderef.unambiguous_final_ty(self); if let Some((did, field_ty)) = private_candidate { - let struct_path = self.tcx().def_path_str(did); - let mut err = struct_span_err!(self.tcx().sess, expr.span, E0616, - "field `{}` of struct `{}` is private", - field, struct_path); - // Also check if an accessible method exists, which is often what is meant. - if self.method_exists(field, expr_t, expr.hir_id, false) - && !self.expr_in_place(expr.hir_id) - { - self.suggest_method_call( - &mut err, - &format!("a method `{}` also exists, call it with parentheses", field), - field, - expr_t, - expr.hir_id, - ); - } - err.emit(); - field_ty - } else if field.name == kw::Invalid { - self.tcx().types.err + self.ban_private_field_access(expr, expr_t, field, did); + return field_ty; + } + + if field.name == kw::Invalid { } else if self.method_exists(field, expr_t, expr.hir_id, true) { - let mut err = type_error_struct!(self.tcx().sess, field.span, expr_t, E0615, - "attempted to take value of method `{}` on type `{}`", - field, expr_t); - - if !self.expr_in_place(expr.hir_id) { - self.suggest_method_call( - &mut err, - "use parentheses to call the method", - field, - expr_t, - expr.hir_id - ); - } else { - err.help("methods are immutable and cannot be assigned to"); + self.ban_take_value_of_method(expr, expr_t, field); + } else if !expr_t.is_primitive_ty() { + let mut err = self.no_such_field_err(field.span, field, expr_t); + + match expr_t.sty { + ty::Adt(def, _) if !def.is_enum() => { + self.suggest_fields_on_recordish(&mut err, def, field); + } + ty::Array(_, len) => { + self.maybe_suggest_array_indexing(&mut err, expr, base, field, len); + } + ty::RawPtr(..) => { + self.suggest_first_deref_field(&mut err, expr, base, field); + } + _ => {} + } + + if field.name == kw::Await { + // We know by construction that `<expr>.await` is either on Rust 2015 + // or results in `ExprKind::Await`. Suggest switching the edition to 2018. + err.note("to `.await` a `Future`, switch to Rust 2018"); + err.help("set `edition = \"2018\"` in `Cargo.toml`"); + err.note("for more on editions, read https://doc.rust-lang.org/edition-guide"); } err.emit(); - self.tcx().types.err } else { - if !expr_t.is_primitive_ty() { - let mut err = self.no_such_field_err(field.span, field, expr_t); - - match expr_t.sty { - ty::Adt(def, _) if !def.is_enum() => { - if let Some(suggested_field_name) = - Self::suggest_field_name(def.non_enum_variant(), - &field.as_str(), vec![]) { - err.span_suggestion( - field.span, - "a field with a similar name exists", - suggested_field_name.to_string(), - Applicability::MaybeIncorrect, - ); - } else { - err.span_label(field.span, "unknown field"); - let struct_variant_def = def.non_enum_variant(); - let field_names = self.available_field_names(struct_variant_def); - if !field_names.is_empty() { - err.note(&format!("available fields are: {}", - self.name_series_display(field_names))); - } - }; - } - ty::Array(_, len) => { - if let (Some(len), Ok(user_index)) = ( - len.try_eval_usize(self.tcx, self.param_env), - field.as_str().parse::<u64>() - ) { - let base = self.tcx.sess.source_map() - .span_to_snippet(base.span) - .unwrap_or_else(|_| - self.tcx.hir().hir_to_pretty_string(base.hir_id)); - let help = "instead of using tuple indexing, use array indexing"; - let suggestion = format!("{}[{}]", base, field); - let applicability = if len < user_index { - Applicability::MachineApplicable - } else { - Applicability::MaybeIncorrect - }; - err.span_suggestion( - expr.span, help, suggestion, applicability - ); - } - } - ty::RawPtr(..) => { - let base = self.tcx.sess.source_map() - .span_to_snippet(base.span) - .unwrap_or_else(|_| self.tcx.hir().hir_to_pretty_string(base.hir_id)); - let msg = format!("`{}` is a raw pointer; try dereferencing it", base); - let suggestion = format!("(*{}).{}", base, field); - err.span_suggestion( - expr.span, - &msg, - suggestion, - Applicability::MaybeIncorrect, - ); - } - _ => {} - } - err + type_error_struct!( + self.tcx().sess, + field.span, + expr_t, + E0610, + "`{}` is a primitive type and therefore doesn't have fields", + expr_t + ) + .emit(); + } + + self.tcx().types.err + } + + fn ban_private_field_access( + &self, + expr: &hir::Expr, + expr_t: Ty<'tcx>, + field: ast::Ident, + base_did: DefId, + ) { + let struct_path = self.tcx().def_path_str(base_did); + let mut err = struct_span_err!( + self.tcx().sess, + expr.span, + E0616, + "field `{}` of struct `{}` is private", + field, + struct_path + ); + // Also check if an accessible method exists, which is often what is meant. + if self.method_exists(field, expr_t, expr.hir_id, false) + && !self.expr_in_place(expr.hir_id) + { + self.suggest_method_call( + &mut err, + &format!("a method `{}` also exists, call it with parentheses", field), + field, + expr_t, + expr.hir_id, + ); + } + err.emit(); + } + + fn ban_take_value_of_method(&self, expr: &hir::Expr, expr_t: Ty<'tcx>, field: ast::Ident) { + let mut err = type_error_struct!( + self.tcx().sess, + field.span, + expr_t, + E0615, + "attempted to take value of method `{}` on type `{}`", + field, + expr_t + ); + + if !self.expr_in_place(expr.hir_id) { + self.suggest_method_call( + &mut err, + "use parentheses to call the method", + field, + expr_t, + expr.hir_id + ); + } else { + err.help("methods are immutable and cannot be assigned to"); + } + + err.emit(); + } + + fn suggest_fields_on_recordish( + &self, + err: &mut DiagnosticBuilder<'_>, + def: &'tcx ty::AdtDef, + field: ast::Ident, + ) { + if let Some(suggested_field_name) = + Self::suggest_field_name(def.non_enum_variant(), &field.as_str(), vec![]) + { + err.span_suggestion( + field.span, + "a field with a similar name exists", + suggested_field_name.to_string(), + Applicability::MaybeIncorrect, + ); + } else { + err.span_label(field.span, "unknown field"); + let struct_variant_def = def.non_enum_variant(); + let field_names = self.available_field_names(struct_variant_def); + if !field_names.is_empty() { + err.note(&format!("available fields are: {}", + self.name_series_display(field_names))); + } + } + } + + fn maybe_suggest_array_indexing( + &self, + err: &mut DiagnosticBuilder<'_>, + expr: &hir::Expr, + base: &hir::Expr, + field: ast::Ident, + len: &ty::Const<'tcx>, + ) { + if let (Some(len), Ok(user_index)) = ( + len.try_eval_usize(self.tcx, self.param_env), + field.as_str().parse::<u64>() + ) { + let base = self.tcx.sess.source_map() + .span_to_snippet(base.span) + .unwrap_or_else(|_| self.tcx.hir().hir_to_pretty_string(base.hir_id)); + let help = "instead of using tuple indexing, use array indexing"; + let suggestion = format!("{}[{}]", base, field); + let applicability = if len < user_index { + Applicability::MachineApplicable } else { - type_error_struct!(self.tcx().sess, field.span, expr_t, E0610, - "`{}` is a primitive type and therefore doesn't have fields", - expr_t) - }.emit(); - self.tcx().types.err + Applicability::MaybeIncorrect + }; + err.span_suggestion(expr.span, help, suggestion, applicability); } } + fn suggest_first_deref_field( + &self, + err: &mut DiagnosticBuilder<'_>, + expr: &hir::Expr, + base: &hir::Expr, + field: ast::Ident, + ) { + let base = self.tcx.sess.source_map() + .span_to_snippet(base.span) + .unwrap_or_else(|_| self.tcx.hir().hir_to_pretty_string(base.hir_id)); + let msg = format!("`{}` is a raw pointer; try dereferencing it", base); + let suggestion = format!("(*{}).{}", base, field); + err.span_suggestion( + expr.span, + &msg, + suggestion, + Applicability::MaybeIncorrect, + ); + } + fn no_such_field_err<T: Display>(&self, span: Span, field: T, expr_t: &ty::TyS<'_>) -> DiagnosticBuilder<'_> { type_error_struct!(self.tcx().sess, span, expr_t, E0609, diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 8bb24eef5e9..dfbf8bcd0f6 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -67,7 +67,7 @@ pub fn intrisic_operation_unsafety(intrinsic: &str) -> hir::Unsafety { match intrinsic { "size_of" | "min_align_of" | "needs_drop" | "add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" | - "overflowing_add" | "overflowing_sub" | "overflowing_mul" | + "wrapping_add" | "wrapping_sub" | "wrapping_mul" | "saturating_add" | "saturating_sub" | "rotate_left" | "rotate_right" | "ctpop" | "ctlz" | "cttz" | "bswap" | "bitreverse" | @@ -314,7 +314,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem) { (1, vec![param(0), param(0)], param(0)), "unchecked_add" | "unchecked_sub" | "unchecked_mul" => (1, vec![param(0), param(0)], param(0)), - "overflowing_add" | "overflowing_sub" | "overflowing_mul" => + "wrapping_add" | "wrapping_sub" | "wrapping_mul" => (1, vec![param(0), param(0)], param(0)), "saturating_add" | "saturating_sub" => (1, vec![param(0), param(0)], param(0)), diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 4a5eba1df88..53024d97c3b 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -985,7 +985,7 @@ impl hir::intravisit::Visitor<'tcx> for UsePlacementFinder<'tcx> { hir::ItemKind::Use(..) => { // Don't suggest placing a `use` before the prelude // import or other generated ones. - if item.span.ctxt().outer_expn_info().is_none() { + if !item.span.from_expansion() { self.span = Some(item.span.shrink_to_lo()); self.found_use = true; return; @@ -995,7 +995,7 @@ impl hir::intravisit::Visitor<'tcx> for UsePlacementFinder<'tcx> { hir::ItemKind::ExternCrate(_) => {} // ...but do place them before the first other item. _ => if self.span.map_or(true, |span| item.span < span ) { - if item.span.ctxt().outer_expn_info().is_none() { + if !item.span.from_expansion() { // Don't insert between attributes and an item. if item.attrs.is_empty() { self.span = Some(item.span.shrink_to_lo()); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 4fb28db6e94..9c7ac83e82e 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1325,12 +1325,94 @@ fn check_union(tcx: TyCtxt<'_>, id: hir::HirId, span: Span) { check_packed(tcx, span, def_id); } +/// Checks that an opaque type does not contain cycles and does not use `Self` or `T::Foo` +/// projections that would result in "inheriting lifetimes". fn check_opaque<'tcx>( tcx: TyCtxt<'tcx>, def_id: DefId, substs: SubstsRef<'tcx>, span: Span, - origin: &hir::OpaqueTyOrigin + origin: &hir::OpaqueTyOrigin, +) { + check_opaque_for_inheriting_lifetimes(tcx, def_id, span); + check_opaque_for_cycles(tcx, def_id, substs, span, origin); +} + +/// Checks that an opaque type does not use `Self` or `T::Foo` projections that would result +/// in "inheriting lifetimes". +fn check_opaque_for_inheriting_lifetimes( + tcx: TyCtxt<'tcx>, + def_id: DefId, + span: Span, +) { + let item = tcx.hir().expect_item( + tcx.hir().as_local_hir_id(def_id).expect("opaque type is not local")); + debug!("check_opaque_for_inheriting_lifetimes: def_id={:?} span={:?} item={:?}", + def_id, span, item); + + #[derive(Debug)] + struct ProhibitOpaqueVisitor<'tcx> { + opaque_identity_ty: Ty<'tcx>, + generics: &'tcx ty::Generics, + }; + + impl<'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueVisitor<'tcx> { + fn visit_ty(&mut self, t: Ty<'tcx>) -> bool { + debug!("check_opaque_for_inheriting_lifetimes: (visit_ty) t={:?}", t); + if t == self.opaque_identity_ty { false } else { t.super_visit_with(self) } + } + + fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool { + debug!("check_opaque_for_inheriting_lifetimes: (visit_region) r={:?}", r); + if let RegionKind::ReEarlyBound(ty::EarlyBoundRegion { index, .. }) = r { + return *index < self.generics.parent_count as u32; + } + + r.super_visit_with(self) + } + } + + let prohibit_opaque = match item.node { + ItemKind::OpaqueTy(hir::OpaqueTy { origin: hir::OpaqueTyOrigin::AsyncFn, .. }) | + ItemKind::OpaqueTy(hir::OpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn, .. }) => { + let mut visitor = ProhibitOpaqueVisitor { + opaque_identity_ty: tcx.mk_opaque( + def_id, InternalSubsts::identity_for_item(tcx, def_id)), + generics: tcx.generics_of(def_id), + }; + debug!("check_opaque_for_inheriting_lifetimes: visitor={:?}", visitor); + + tcx.predicates_of(def_id).predicates.iter().any( + |(predicate, _)| predicate.visit_with(&mut visitor)) + }, + _ => false, + }; + + debug!("check_opaque_for_inheriting_lifetimes: prohibit_opaque={:?}", prohibit_opaque); + if prohibit_opaque { + let is_async = match item.node { + ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => match origin { + hir::OpaqueTyOrigin::AsyncFn => true, + _ => false, + }, + _ => unreachable!(), + }; + + tcx.sess.span_err(span, &format!( + "`{}` return type cannot contain a projection or `Self` that references lifetimes from \ + a parent scope", + if is_async { "async fn" } else { "impl Trait" }, + )); + } +} + +/// Checks that an opaque type does not contain cycles. +fn check_opaque_for_cycles<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: DefId, + substs: SubstsRef<'tcx>, + span: Span, + origin: &hir::OpaqueTyOrigin, ) { if let Err(partially_expanded_type) = tcx.try_expand_impl_trait_type(def_id, substs) { if let hir::OpaqueTyOrigin::AsyncFn = origin { @@ -1834,9 +1916,7 @@ fn bad_variant_count<'tcx>(tcx: TyCtxt<'tcx>, adt: &'tcx ty::AdtDef, sp: Span, d ); let mut err = struct_span_err!(tcx.sess, sp, E0731, "transparent enum {}", msg); err.span_label(sp, &msg); - if let &[.., ref end] = &variant_spans[..] { - // FIXME: Ping cfg(bootstrap) -- Use `ref start @ ..` with new bootstrap compiler. - let start = &variant_spans[..variant_spans.len() - 1]; + if let &[ref start @ .., ref end] = &variant_spans[..] { for variant_span in start { err.span_label(*variant_span, ""); } @@ -1968,19 +2048,19 @@ pub fn check_enum<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, vs: &'tcx [hir::Variant], i } for v in vs { - if let Some(ref e) = v.node.disr_expr { + if let Some(ref e) = v.disr_expr { tcx.typeck_tables_of(tcx.hir().local_def_id(e.hir_id)); } } if tcx.adt_def(def_id).repr.int.is_none() && tcx.features().arbitrary_enum_discriminant { let is_unit = - |var: &hir::Variant| match var.node.data { + |var: &hir::Variant| match var.data { hir::VariantData::Unit(..) => true, _ => false }; - let has_disr = |var: &hir::Variant| var.node.disr_expr.is_some(); + let has_disr = |var: &hir::Variant| var.disr_expr.is_some(); let has_non_units = vs.iter().any(|var| !is_unit(var)); let disr_units = vs.iter().any(|var| is_unit(&var) && has_disr(&var)); let disr_non_unit = vs.iter().any(|var| !is_unit(&var) && has_disr(&var)); @@ -1999,11 +2079,11 @@ pub fn check_enum<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, vs: &'tcx [hir::Variant], i let variant_did = def.variants[VariantIdx::new(i)].def_id; let variant_i_hir_id = tcx.hir().as_local_hir_id(variant_did).unwrap(); let variant_i = tcx.hir().expect_variant(variant_i_hir_id); - let i_span = match variant_i.node.disr_expr { + let i_span = match variant_i.disr_expr { Some(ref expr) => tcx.hir().span(expr.hir_id), None => tcx.hir().span(variant_i_hir_id) }; - let span = match v.node.disr_expr { + let span = match v.disr_expr { Some(ref expr) => tcx.hir().span(expr.hir_id), None => v.span }; @@ -2863,7 +2943,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (PlaceOp::Index, false) => (self.tcx.lang_items().index_trait(), sym::index), (PlaceOp::Index, true) => (self.tcx.lang_items().index_mut_trait(), sym::index_mut), }; - (tr, ast::Ident::with_empty_ctxt(name)) + (tr, ast::Ident::with_dummy_span(name)) } fn try_overloaded_place_op(&self, @@ -3820,6 +3900,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err, &fn_decl, expected, found, can_suggest); } self.suggest_ref_or_into(err, expression, expected, found); + self.suggest_boxing_when_appropriate(err, expression, expected, found); pointing_at_return_type } @@ -3980,6 +4061,41 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + /// When encountering the expected boxed value allocated in the stack, suggest allocating it + /// in the heap by calling `Box::new()`. + fn suggest_boxing_when_appropriate( + &self, + err: &mut DiagnosticBuilder<'tcx>, + expr: &hir::Expr, + expected: Ty<'tcx>, + found: Ty<'tcx>, + ) { + if self.tcx.hir().is_const_context(expr.hir_id) { + // Do not suggest `Box::new` in const context. + return; + } + if !expected.is_box() || found.is_box() { + return; + } + let boxed_found = self.tcx.mk_box(found); + if let (true, Ok(snippet)) = ( + self.can_coerce(boxed_found, expected), + self.sess().source_map().span_to_snippet(expr.span), + ) { + err.span_suggestion( + expr.span, + "store this in the heap by calling `Box::new`", + format!("Box::new({})", snippet), + Applicability::MachineApplicable, + ); + err.note("for more on the distinction between the stack and the \ + heap, read https://doc.rust-lang.org/book/ch15-01-box.html, \ + https://doc.rust-lang.org/rust-by-example/std/box.html, and \ + https://doc.rust-lang.org/std/boxed/index.html"); + } + } + + /// A common error is to forget to add a semicolon at the end of a block, e.g., /// /// ``` @@ -4081,8 +4197,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// A possible error is to forget to add `.await` when using futures: /// /// ``` - /// #![feature(async_await)] - /// /// async fn make_u32() -> u32 { /// 22 /// } diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index c1d8fde3be1..9c6ea7d30cc 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -191,7 +191,7 @@ fn check_associated_item( let item = fcx.tcx.associated_item(fcx.tcx.hir().local_def_id(item_id)); let (mut implied_bounds, self_ty) = match item.container { - ty::TraitContainer(_) => (vec![], fcx.tcx.mk_self_type()), + ty::TraitContainer(_) => (vec![], fcx.tcx.types.self_param), ty::ImplContainer(def_id) => (fcx.impl_implied_bounds(def_id, span), fcx.tcx.type_of(def_id)) }; @@ -203,7 +203,6 @@ fn check_associated_item( fcx.register_wf_obligation(ty, span, code.clone()); } ty::AssocKind::Method => { - reject_shadowing_parameters(fcx.tcx, item.def_id); let sig = fcx.tcx.fn_sig(item.def_id); let sig = fcx.normalize_associated_types_in(span, &sig); check_fn_or_method(tcx, fcx, span, sig, @@ -998,34 +997,6 @@ fn report_bivariance(tcx: TyCtxt<'_>, span: Span, param_name: ast::Name) { err.emit(); } -fn reject_shadowing_parameters(tcx: TyCtxt<'_>, def_id: DefId) { - let generics = tcx.generics_of(def_id); - let parent = tcx.generics_of(generics.parent.unwrap()); - let impl_params: FxHashMap<_, _> = parent.params.iter().flat_map(|param| match param.kind { - GenericParamDefKind::Lifetime => None, - GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => { - Some((param.name, param.def_id)) - } - }).collect(); - - for method_param in &generics.params { - // Shadowing is checked in `resolve_lifetime`. - if let GenericParamDefKind::Lifetime = method_param.kind { - continue - } - if impl_params.contains_key(&method_param.name) { - // Tighten up the span to focus on only the shadowing type. - let type_span = tcx.def_span(method_param.def_id); - - // The expectation here is that the original trait declaration is - // local so it should be okay to just unwrap everything. - let trait_def_id = impl_params[&method_param.name]; - let trait_decl_span = tcx.def_span(trait_def_id); - error_194(tcx, type_span, trait_decl_span, &method_param.name.as_str()[..]); - } - } -} - /// Feature gates RFC 2056 -- trivial bounds, checking for global bounds that /// aren't true. fn check_false_global_bounds(fcx: &FnCtxt<'_, '_>, span: Span, id: hir::HirId) { @@ -1119,7 +1090,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn enum_variants(&self, enum_def: &hir::EnumDef) -> Vec<AdtVariant<'tcx>> { enum_def.variants.iter() - .map(|variant| self.non_enum_variant(&variant.node.data)) + .map(|variant| self.non_enum_variant(&variant.data)) .collect() } @@ -1152,12 +1123,3 @@ fn error_392( err.span_label(span, "unused parameter"); err } - -fn error_194(tcx: TyCtxt<'_>, span: Span, trait_decl_span: Span, name: &str) { - struct_span_err!(tcx.sess, span, E0194, - "type parameter `{}` shadows another type parameter of the same name", - name) - .span_label(span, "shadows another type parameter") - .span_label(trait_decl_span, format!("first `{}` declared here", name)) - .emit(); -} diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 67a8ecaf1da..a88e32eb34d 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -283,7 +283,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> { } hir::PatKind::Struct(_, ref fields, _) => { for field in fields { - self.visit_field_id(field.node.hir_id); + self.visit_field_id(field.hir_id); } } _ => {} diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 0f0568907c6..312a598af02 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -35,7 +35,6 @@ use rustc_target::spec::abi; use syntax::ast; use syntax::ast::{Ident, MetaItemKind}; use syntax::attr::{InlineAttr, OptimizeAttr, list_contains_name, mark_used}; -use syntax::source_map::Spanned; use syntax::feature_gate; use syntax::symbol::{InternedString, kw, Symbol, sym}; use syntax_pos::{Span, DUMMY_SP}; @@ -520,7 +519,11 @@ fn convert_variant_ctor(tcx: TyCtxt<'_>, ctor_id: hir::HirId) { tcx.predicates_of(def_id); } -fn convert_enum_variant_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, variants: &[hir::Variant]) { +fn convert_enum_variant_types<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: DefId, + variants: &[hir::Variant] +) { let def = tcx.adt_def(def_id); let repr_type = def.repr.discr_type(); let initial = repr_type.initial_discriminant(tcx); @@ -530,7 +533,7 @@ fn convert_enum_variant_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, variants: for variant in variants { let wrapped_discr = prev_discr.map_or(initial, |d| d.wrap_incr(tcx)); prev_discr = Some( - if let Some(ref e) = variant.node.disr_expr { + if let Some(ref e) = variant.disr_expr { let expr_did = tcx.hir().local_def_id(e.hir_id); def.eval_explicit_discr(tcx, expr_did) } else if let Some(discr) = repr_type.disr_incr(tcx, prev_discr) { @@ -546,14 +549,14 @@ fn convert_enum_variant_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, variants: format!("overflowed on value after {}", prev_discr.unwrap()), ).note(&format!( "explicitly set `{} = {}` if that is desired outcome", - variant.node.ident, wrapped_discr + variant.ident, wrapped_discr )) .emit(); None }.unwrap_or(wrapped_discr), ); - for f in variant.node.data.fields() { + for f in variant.data.fields() { let def_id = tcx.hir().local_def_id(f.hir_id); tcx.generics_of(def_id); tcx.type_of(def_id); @@ -562,7 +565,7 @@ fn convert_enum_variant_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, variants: // Convert the ctor, if any. This also registers the variant as // an item. - if let Some(ctor_hir_id) = variant.node.data.ctor_hir_id() { + if let Some(ctor_hir_id) = variant.data.ctor_hir_id() { convert_variant_ctor(tcx, ctor_hir_id); } } @@ -641,11 +644,11 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::AdtDef { let variants = def.variants .iter() .map(|v| { - let variant_did = Some(tcx.hir().local_def_id(v.node.id)); - let ctor_did = v.node.data.ctor_hir_id() + let variant_did = Some(tcx.hir().local_def_id(v.id)); + let ctor_did = v.data.ctor_hir_id() .map(|hir_id| tcx.hir().local_def_id(hir_id)); - let discr = if let Some(ref e) = v.node.disr_expr { + let discr = if let Some(ref e) = v.disr_expr { distance_from_explicit = 0; ty::VariantDiscr::Explicit(tcx.hir().local_def_id(e.hir_id)) } else { @@ -653,8 +656,8 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::AdtDef { }; distance_from_explicit += 1; - convert_variant(tcx, variant_did, ctor_did, v.node.ident, discr, - &v.node.data, AdtKind::Enum, def_id) + convert_variant(tcx, variant_did, ctor_did, v.ident, discr, + &v.data, AdtKind::Enum, def_id) }) .collect(); @@ -713,7 +716,7 @@ fn super_predicates_of( let icx = ItemCtxt::new(tcx, trait_def_id); // Convert the bounds that follow the colon, e.g., `Bar + Zed` in `trait Foo: Bar + Zed`. - let self_param_ty = tcx.mk_self_type(); + let self_param_ty = tcx.types.self_param; let superbounds1 = AstConv::compute_bounds(&icx, self_param_ty, bounds, SizedByDefault::No, item.span); @@ -897,6 +900,20 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics { let parent_id = tcx.hir().get_parent_item(hir_id); Some(tcx.hir().local_def_id(parent_id)) } + // FIXME(#43408) enable this in all cases when we get lazy normalization. + Node::AnonConst(&anon_const) => { + // HACK(eddyb) this provides the correct generics when the workaround + // for a const parameter `AnonConst` is being used elsewhere, as then + // there won't be the kind of cyclic dependency blocking #43408. + let expr = &tcx.hir().body(anon_const.body).value; + let icx = ItemCtxt::new(tcx, def_id); + if AstConv::const_param_def_id(&icx, expr).is_some() { + let parent_id = tcx.hir().get_parent_item(hir_id); + Some(tcx.hir().local_def_id(parent_id)) + } else { + None + } + } Node::Expr(&hir::Expr { node: hir::ExprKind::Closure(..), .. @@ -1011,13 +1028,6 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics { synthetic, .. } => { - if param.name.ident().name == kw::SelfUpper { - span_bug!( - param.span, - "`Self` should not be the name of a regular parameter" - ); - } - if !allow_defaults && default.is_some() { if !tcx.features().default_type_parameter_fallback { tcx.lint_hir( @@ -1041,13 +1051,6 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics { } } GenericParamKind::Const { .. } => { - if param.name.ident().name == kw::SelfUpper { - span_bug!( - param.span, - "`Self` should not be the name of a regular parameter", - ); - } - ty::GenericParamDefKind::Const } _ => return None, @@ -1314,10 +1317,9 @@ pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option<Ty< ForeignItemKind::Type => tcx.mk_foreign(def_id), }, - Node::Ctor(&ref def) | Node::Variant(&Spanned { - node: hir::VariantKind { data: ref def, .. }, - .. - }) => match *def { + Node::Ctor(&ref def) | Node::Variant( + hir::Variant { data: ref def, .. } + ) => match *def { VariantData::Unit(..) | VariantData::Struct(..) => { tcx.type_of(tcx.hir().get_parent_did(hir_id)) } @@ -1363,12 +1365,8 @@ pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option<Ty< tcx.types.usize } - Node::Variant(&Spanned { - node: - VariantKind { - disr_expr: Some(ref e), - .. - }, + Node::Variant(Variant { + disr_expr: Some(ref e), .. }) if e.hir_id == hir_id => { @@ -1569,7 +1567,7 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { &format!( "defining opaque type use restricts opaque \ type by using the generic parameter `{}` twice", - p.name + p, ), ); return; @@ -1809,10 +1807,9 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { compute_sig_of_foreign_fn_decl(tcx, def_id, fn_decl, abi) } - Ctor(data) | Variant(Spanned { - node: hir::VariantKind { data, .. }, - .. - }) if data.ctor_hir_id().is_some() => { + Ctor(data) | Variant( + hir::Variant { data, .. } + ) if data.ctor_hir_id().is_some() => { let ty = tcx.type_of(tcx.hir().get_parent_did(hir_id)); let inputs = data.fields() .iter() diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs index 90118a9f191..b52183d4b1b 100644 --- a/src/librustc_typeck/error_codes.rs +++ b/src/librustc_typeck/error_codes.rs @@ -1718,22 +1718,6 @@ Since we know for certain that `Wrapper<u32>` implements `Clone`, there's no reason to also specify it in a `where` clause. "##, -E0194: r##" -A type parameter was declared which shadows an existing one. An example of this -error: - -```compile_fail,E0194 -trait Foo<T> { - fn do_something(&self) -> T; - fn do_something_else<T: Clone>(&self, bar: T); -} -``` - -In this example, the trait `Foo` and the trait method `do_something_else` both -define a type parameter `T`. This is not allowed: if the method wishes to -define a type parameter, it must use a different name for it. -"##, - E0195: r##" Your method's lifetime parameters do not match the trait declaration. Erroneous code example: @@ -4767,7 +4751,6 @@ E0733: r##" Recursion in an `async fn` requires boxing. For example, this will not compile: ```edition2018,compile_fail,E0733 -#![feature(async_await)] async fn foo(n: usize) { if n > 0 { foo(n - 1).await; @@ -4779,12 +4762,11 @@ To achieve async recursion, the `async fn` needs to be desugared such that the `Future` is explicit in the return type: ```edition2018,compile_fail,E0720 -# #![feature(async_await)] use std::future::Future; -fn foo_desugered(n: usize) -> impl Future<Output = ()> { +fn foo_desugared(n: usize) -> impl Future<Output = ()> { async move { if n > 0 { - foo_desugered(n - 1).await; + foo_desugared(n - 1).await; } } } @@ -4793,7 +4775,6 @@ fn foo_desugered(n: usize) -> impl Future<Output = ()> { Finally, the future is wrapped in a pinned box: ```edition2018 -# #![feature(async_await)] use std::future::Future; use std::pin::Pin; fn foo_recursive(n: usize) -> Pin<Box<dyn Future<Output = ()>>> { @@ -4837,6 +4818,7 @@ register_diagnostics! { // 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 +// E0194, // merged into E0403 // E0196, // cannot determine a type for this closure E0203, // type parameter has more than one relaxed default bound, // and only one is supported diff --git a/src/librustc_typeck/outlives/implicit_infer.rs b/src/librustc_typeck/outlives/implicit_infer.rs index 6b288347ad0..644d723ded5 100644 --- a/src/librustc_typeck/outlives/implicit_infer.rs +++ b/src/librustc_typeck/outlives/implicit_infer.rs @@ -3,7 +3,6 @@ use rustc::hir::def_id::DefId; use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::ty::subst::{Kind, Subst, UnpackedKind}; use rustc::ty::{self, Ty, TyCtxt}; -use rustc::ty::fold::TypeFoldable; use rustc::util::nodemap::FxHashMap; use super::explicit::ExplicitPredicatesMap; @@ -178,11 +177,11 @@ fn insert_required_predicates_to_be_wf<'tcx>( // let _: () = substs.region_at(0); check_explicit_predicates( tcx, - &def.did, + def.did, substs, required_predicates, explicit_map, - IgnoreSelfTy(false), + None, ); } @@ -208,11 +207,11 @@ fn insert_required_predicates_to_be_wf<'tcx>( .substs; check_explicit_predicates( tcx, - &ex_trait_ref.skip_binder().def_id, + ex_trait_ref.skip_binder().def_id, substs, required_predicates, explicit_map, - IgnoreSelfTy(true), + Some(tcx.types.self_param), ); } } @@ -223,11 +222,11 @@ fn insert_required_predicates_to_be_wf<'tcx>( debug!("Projection"); check_explicit_predicates( tcx, - &tcx.associated_item(obj.item_def_id).container.id(), + tcx.associated_item(obj.item_def_id).container.id(), obj.substs, required_predicates, explicit_map, - IgnoreSelfTy(false), + None, ); } @@ -236,9 +235,6 @@ fn insert_required_predicates_to_be_wf<'tcx>( } } -#[derive(Debug)] -pub struct IgnoreSelfTy(bool); - /// We also have to check the explicit predicates /// declared on the type. /// @@ -256,25 +252,25 @@ pub struct IgnoreSelfTy(bool); /// applying the substitution as above. pub fn check_explicit_predicates<'tcx>( tcx: TyCtxt<'tcx>, - def_id: &DefId, + def_id: DefId, substs: &[Kind<'tcx>], required_predicates: &mut RequiredPredicates<'tcx>, explicit_map: &mut ExplicitPredicatesMap<'tcx>, - ignore_self_ty: IgnoreSelfTy, + ignored_self_ty: Option<Ty<'tcx>>, ) { debug!( "check_explicit_predicates(def_id={:?}, \ substs={:?}, \ explicit_map={:?}, \ required_predicates={:?}, \ - ignore_self_ty={:?})", + ignored_self_ty={:?})", def_id, substs, explicit_map, required_predicates, - ignore_self_ty, + ignored_self_ty, ); - let explicit_predicates = explicit_map.explicit_predicates_of(tcx, *def_id); + let explicit_predicates = explicit_map.explicit_predicates_of(tcx, def_id); for outlives_predicate in explicit_predicates.iter() { debug!("outlives_predicate = {:?}", &outlives_predicate); @@ -313,9 +309,9 @@ pub fn check_explicit_predicates<'tcx>( // = X` binding from the object type (there must be such a // binding) and thus infer an outlives requirement that `X: // 'b`. - if ignore_self_ty.0 { + if let Some(self_ty) = ignored_self_ty { if let UnpackedKind::Type(ty) = outlives_predicate.0.unpack() { - if ty.has_self_ty() { + if ty.walk().any(|ty| ty == self_ty) { debug!("skipping self ty = {:?}", &ty); continue; } diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index b75a0912657..7ed9d6606f6 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -82,8 +82,8 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> { self.visit_node_helper(item.hir_id); for variant in &enum_def.variants { - if let hir::VariantData::Tuple(..) = variant.node.data { - self.visit_node_helper(variant.node.data.ctor_hir_id().unwrap()); + if let hir::VariantData::Tuple(..) = variant.data { + self.visit_node_helper(variant.data.ctor_hir_id().unwrap()); } } } diff --git a/src/librustc_typeck/variance/terms.rs b/src/librustc_typeck/variance/terms.rs index 7af7c79bb3c..e10837e52ad 100644 --- a/src/librustc_typeck/variance/terms.rs +++ b/src/librustc_typeck/variance/terms.rs @@ -145,8 +145,8 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for TermsContext<'a, 'tcx> { self.add_inferreds_for_item(item.hir_id); for variant in &enum_def.variants { - if let hir::VariantData::Tuple(..) = variant.node.data { - self.add_inferreds_for_item(variant.node.data.ctor_hir_id().unwrap()); + if let hir::VariantData::Tuple(..) = variant.data { + self.add_inferreds_for_item(variant.data.ctor_hir_id().unwrap()); } } } diff --git a/src/librustdoc/clean/cfg/tests.rs b/src/librustdoc/clean/cfg/tests.rs index 405144b444f..ec5d86b2c61 100644 --- a/src/librustdoc/clean/cfg/tests.rs +++ b/src/librustdoc/clean/cfg/tests.rs @@ -3,7 +3,6 @@ use super::*; use syntax_pos::DUMMY_SP; use syntax::ast::*; use syntax::attr; -use syntax::source_map::dummy_spanned; use syntax::symbol::Symbol; use syntax::with_default_globals; @@ -181,7 +180,8 @@ fn test_parse_ok() { let mi = attr::mk_name_value_item_str( Ident::from_str("all"), - dummy_spanned(Symbol::intern("done")) + Symbol::intern("done"), + DUMMY_SP, ); assert_eq!(Cfg::parse(&mi), Ok(name_value_cfg("all", "done"))); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index b281505956d..9b4803ce41e 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -29,7 +29,7 @@ use rustc::util::nodemap::{FxHashMap, FxHashSet}; use syntax::ast::{self, AttrStyle, Ident}; use syntax::attr; use syntax::ext::base::MacroKind; -use syntax::source_map::{dummy_spanned, Spanned}; +use syntax::source_map::DUMMY_SP; use syntax::symbol::{Symbol, kw, sym}; use syntax::symbol::InternedString; use syntax_pos::{self, Pos, FileName}; @@ -930,8 +930,8 @@ impl Attributes { if attr.check_name(sym::enable) { if let Some(feat) = attr.value_str() { let meta = attr::mk_name_value_item_str( - Ident::with_empty_ctxt(sym::target_feature), - dummy_spanned(feat)); + Ident::with_dummy_span(sym::target_feature), feat, DUMMY_SP + ); if let Ok(feat_cfg) = Cfg::parse(&meta) { cfg &= feat_cfg; } @@ -2303,7 +2303,7 @@ impl Clean<Item> for ty::AssocItem { ty::ImplContainer(def_id) => { cx.tcx.type_of(def_id) } - ty::TraitContainer(_) => cx.tcx.mk_self_type() + ty::TraitContainer(_) => cx.tcx.types.self_param, }; let self_arg_ty = *sig.input(0).skip_binder(); if self_arg_ty == self_ty { @@ -4102,12 +4102,14 @@ fn name_from_pat(p: &hir::Pat) -> String { PatKind::TupleStruct(ref p, ..) | PatKind::Path(ref p) => qpath_to_string(p), PatKind::Struct(ref name, ref fields, etc) => { format!("{} {{ {}{} }}", qpath_to_string(name), - fields.iter().map(|&Spanned { node: ref fp, .. }| - format!("{}: {}", fp.ident, name_from_pat(&*fp.pat))) + fields.iter().map(|fp| format!("{}: {}", fp.ident, name_from_pat(&fp.pat))) .collect::<Vec<String>>().join(", "), if etc { ", .." } else { "" } ) } + PatKind::Or(ref pats) => { + pats.iter().map(|p| name_from_pat(&**p)).collect::<Vec<String>>().join(" | ") + } PatKind::Tuple(ref elts, _) => format!("({})", elts.iter().map(|p| name_from_pat(&**p)) .collect::<Vec<String>>().join(", ")), PatKind::Box(ref p) => name_from_pat(&**p), diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index e4fba73b820..3801c42307f 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -149,9 +149,11 @@ fn trait_is_same_or_supertrait(cx: &DocContext<'_>, child: DefId, return true } let predicates = cx.tcx.super_predicates_of(child); + debug_assert!(cx.tcx.generics_of(child).has_self); + let self_ty = cx.tcx.types.self_param; predicates.predicates.iter().filter_map(|(pred, _)| { if let ty::Predicate::Trait(ref pred) = *pred { - if pred.skip_binder().trait_ref.self_ty().is_self() { + if pred.skip_binder().trait_ref.self_ty() == self_ty { Some(pred.def_id()) } else { None diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 5c9fac7eab4..c73c46472d8 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -4,6 +4,7 @@ use rustc::hir::def_id::DefId; use rustc::hir; use rustc::lint as lint; use rustc::ty; +use rustc_resolve::ParentScope; use syntax; use syntax::ast::{self, Ident}; use syntax::ext::base::SyntaxExtensionKind; @@ -431,7 +432,7 @@ fn macro_resolve(cx: &DocContext<'_>, path_str: &str) -> Option<Res> { 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, &resolver.dummy_parent_scope(), 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"))); diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 462e21b8f6b..83a8d3fc109 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -951,7 +951,7 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirCollector<'a, 'hir> { v: &'hir hir::Variant, g: &'hir hir::Generics, item_id: hir::HirId) { - self.visit_testable(v.node.ident.to_string(), &v.node.attrs, |this| { + self.visit_testable(v.ident.to_string(), &v.attrs, |this| { intravisit::walk_variant(this, v, g, item_id); }); } diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 35b6d9972da..903ed3aae14 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -130,10 +130,10 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { Enum { name, variants: def.variants.iter().map(|v| Variant { - name: v.node.ident.name, - id: v.node.id, - attrs: &v.node.attrs, - def: &v.node.data, + name: v.ident.name, + id: v.id, + attrs: &v.attrs, + def: &v.data, whence: v.span, }).collect(), vis: &it.vis, diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index 5334c4dfc68..bb77a5bdea4 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -23,10 +23,10 @@ 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.4.0", features = ['rustc-dep-of-std'] } +hashbrown = { version = "0.5.0", features = ['rustc-dep-of-std'] } [dependencies.backtrace] -version = "0.3.34" +version = "0.3.35" default-features = false # don't use coresymbolication on OSX features = [ "rustc-dep-of-std", # enable build support for integrating into libstd diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 1e28ee8da26..a0538986a22 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -6,7 +6,7 @@ use hashbrown::hash_map as base; use crate::borrow::Borrow; use crate::cell::Cell; -use crate::collections::CollectionAllocErr; +use crate::collections::TryReserveError; use crate::fmt::{self, Debug}; #[allow(deprecated)] use crate::hash::{BuildHasher, Hash, Hasher, SipHasher13}; @@ -588,7 +588,7 @@ where /// ``` #[inline] #[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] - pub fn try_reserve(&mut self, additional: usize) -> Result<(), CollectionAllocErr> { + pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { self.base .try_reserve(additional) .map_err(map_collection_alloc_err) @@ -2542,10 +2542,13 @@ fn map_entry<'a, K: 'a, V: 'a>(raw: base::RustcEntry<'a, K, V>) -> Entry<'a, K, } #[inline] -fn map_collection_alloc_err(err: hashbrown::CollectionAllocErr) -> CollectionAllocErr { +fn map_collection_alloc_err(err: hashbrown::CollectionAllocErr) -> TryReserveError { match err { - hashbrown::CollectionAllocErr::CapacityOverflow => CollectionAllocErr::CapacityOverflow, - hashbrown::CollectionAllocErr::AllocErr => CollectionAllocErr::AllocErr, + hashbrown::CollectionAllocErr::CapacityOverflow => TryReserveError::CapacityOverflow, + hashbrown::CollectionAllocErr::AllocErr { layout } => TryReserveError::AllocError { + layout, + non_exhaustive: (), + }, } } @@ -2605,7 +2608,7 @@ mod test_map { use super::RandomState; use crate::cell::RefCell; use rand::{thread_rng, Rng}; - use realstd::collections::CollectionAllocErr::*; + use realstd::collections::TryReserveError::*; use realstd::usize; // https://github.com/rust-lang/rust/issues/62301 @@ -3405,7 +3408,7 @@ mod test_map { panic!("usize::MAX should trigger an overflow!"); } - if let Err(AllocErr) = empty_bytes.try_reserve(MAX_USIZE / 8) { + if let Err(AllocError { .. }) = empty_bytes.try_reserve(MAX_USIZE / 8) { } else { panic!("usize::MAX / 8 should trigger an OOM!") } diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index d243412405a..26db651ef89 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -1,5 +1,5 @@ use crate::borrow::Borrow; -use crate::collections::CollectionAllocErr; +use crate::collections::TryReserveError; use crate::fmt; use crate::hash::{Hash, BuildHasher}; use crate::iter::{Chain, FromIterator, FusedIterator}; @@ -383,7 +383,7 @@ impl<T, S> HashSet<T, S> /// ``` #[inline] #[unstable(feature = "try_reserve", reason = "new API", issue="48043")] - pub fn try_reserve(&mut self, additional: usize) -> Result<(), CollectionAllocErr> { + pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { self.map.try_reserve(additional) } diff --git a/src/libstd/collections/mod.rs b/src/libstd/collections/mod.rs index 15c2532f8b4..f5957466be8 100644 --- a/src/libstd/collections/mod.rs +++ b/src/libstd/collections/mod.rs @@ -427,7 +427,7 @@ pub use self::hash_map::HashMap; pub use self::hash_set::HashSet; #[unstable(feature = "try_reserve", reason = "new API", issue="48043")] -pub use alloc_crate::collections::CollectionAllocErr; +pub use alloc_crate::collections::TryReserveError; mod hash; diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index f2b6ce6feb2..5060f368229 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -353,12 +353,17 @@ fn append_to_string<F>(buf: &mut String, f: F) -> Result<usize> // Because we're extending the buffer with uninitialized data for trusted // readers, we need to make sure to truncate that if any of this panics. fn read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>) -> Result<usize> { - read_to_end_with_reservation(r, buf, 32) + read_to_end_with_reservation(r, buf, |_| 32) } -fn read_to_end_with_reservation<R: Read + ?Sized>(r: &mut R, - buf: &mut Vec<u8>, - reservation_size: usize) -> Result<usize> +fn read_to_end_with_reservation<R, F>( + r: &mut R, + buf: &mut Vec<u8>, + mut reservation_size: F, +) -> Result<usize> +where + R: Read + ?Sized, + F: FnMut(&R) -> usize, { let start_len = buf.len(); let mut g = Guard { len: buf.len(), buf: buf }; @@ -366,7 +371,7 @@ fn read_to_end_with_reservation<R: Read + ?Sized>(r: &mut R, loop { if g.len == g.buf.len() { unsafe { - g.buf.reserve(reservation_size); + g.buf.reserve(reservation_size(r)); let capacity = g.buf.capacity(); g.buf.set_len(capacity); r.initializer().initialize(&mut g.buf[g.len..]); @@ -2253,9 +2258,10 @@ impl<T: Read> Read for Take<T> { } fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize> { - let reservation_size = cmp::min(self.limit, 32) as usize; - - read_to_end_with_reservation(self, buf, reservation_size) + // Pass in a reservation_size closure that respects the current value + // of limit for each read. If we hit the read limit, this prevents the + // final zero-byte read from allocating again. + read_to_end_with_reservation(self, buf, |self_| cmp::min(self_.limit, 32) as usize) } } @@ -2378,6 +2384,7 @@ impl<B: BufRead> Iterator for Lines<B> { #[cfg(test)] mod tests { + use crate::cmp; use crate::io::prelude::*; use super::{Cursor, SeekFrom, repeat}; use crate::io::{self, IoSlice, IoSliceMut}; @@ -2651,6 +2658,49 @@ mod tests { Ok(()) } + // A simple example reader which uses the default implementation of + // read_to_end. + struct ExampleSliceReader<'a> { + slice: &'a [u8], + } + + impl<'a> Read for ExampleSliceReader<'a> { + fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { + let len = cmp::min(self.slice.len(), buf.len()); + buf[..len].copy_from_slice(&self.slice[..len]); + self.slice = &self.slice[len..]; + Ok(len) + } + } + + #[test] + fn test_read_to_end_capacity() -> io::Result<()> { + let input = &b"foo"[..]; + + // read_to_end() generally needs to over-allocate, both for efficiency + // and so that it can distinguish EOF. Assert that this is the case + // with this simple ExampleSliceReader struct, which uses the default + // implementation of read_to_end. Even though vec1 is allocated with + // exactly enough capacity for the read, read_to_end will allocate more + // space here. + let mut vec1 = Vec::with_capacity(input.len()); + ExampleSliceReader { slice: input }.read_to_end(&mut vec1)?; + assert_eq!(vec1.len(), input.len()); + assert!(vec1.capacity() > input.len(), "allocated more"); + + // However, std::io::Take includes an implementation of read_to_end + // that will not allocate when the limit has already been reached. In + // this case, vec2 never grows. + let mut vec2 = Vec::with_capacity(input.len()); + ExampleSliceReader { slice: input } + .take(input.len() as u64) + .read_to_end(&mut vec2)?; + assert_eq!(vec2.len(), input.len()); + assert_eq!(vec2.capacity(), input.len(), "did not allocate more"); + + Ok(()) + } + #[test] fn io_slice_mut_advance() { let mut buf1 = [1; 8]; diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs index f5018485ef7..85a9dea09ed 100644 --- a/src/libstd/keyword_docs.rs +++ b/src/libstd/keyword_docs.rs @@ -984,7 +984,6 @@ mod where_keyword { } // 2018 Edition keywords -#[unstable(feature = "async_await", issue = "50547")] #[doc(keyword = "async")] // /// Return a [`Future`] instead of blocking the current thread. @@ -995,7 +994,6 @@ mod where_keyword { } /// [not yet complete]: https://github.com/rust-lang/rust/issues/34601 mod async_keyword { } -#[unstable(feature = "async_await", issue = "50547")] #[doc(keyword = "await")] // /// Suspend execution until the result of a [`Future`] is ready. diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index ba80d1b7004..c3882bacf87 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -228,7 +228,6 @@ // std is implemented with unstable features, many of which are internal // compiler details that will never be stable // NB: the following list is sorted to minimize merge conflicts. -#![cfg_attr(not(bootstrap), feature(__rust_unstable_column))] #![feature(alloc_error_handler)] #![feature(alloc_layout_extra)] #![feature(allocator_api)] @@ -251,6 +250,7 @@ #![feature(concat_idents)] #![feature(const_cstr_unchecked)] #![feature(const_raw_ptr_deref)] +#![feature(container_error_extra)] #![feature(core_intrinsics)] #![feature(custom_test_frameworks)] #![feature(doc_alias)] @@ -513,7 +513,7 @@ pub use std_detect::detect; // Re-export macros defined in libcore. #[stable(feature = "rust1", since = "1.0.0")] -#[allow(deprecated_in_future)] +#[allow(deprecated, deprecated_in_future)] pub use core::{ // Stable assert_eq, @@ -531,7 +531,6 @@ pub use core::{ }; // Re-export built-in macros defined through libcore. -#[cfg(not(bootstrap))] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] pub use core::{ // Stable @@ -551,7 +550,6 @@ pub use core::{ option_env, stringify, // Unstable - __rust_unstable_column, asm, concat_idents, format_args_nl, diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index f2000936b9a..cbeaf20b13a 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -53,20 +53,20 @@ /// ``` #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] -#[allow_internal_unstable(__rust_unstable_column, libstd_sys_internals)] +#[allow_internal_unstable(libstd_sys_internals)] macro_rules! panic { () => ({ $crate::panic!("explicit panic") }); ($msg:expr) => ({ - $crate::rt::begin_panic($msg, &(file!(), line!(), __rust_unstable_column!())) + $crate::rt::begin_panic($msg, &($crate::file!(), $crate::line!(), $crate::column!())) }); ($msg:expr,) => ({ $crate::panic!($msg) }); ($fmt:expr, $($arg:tt)+) => ({ - $crate::rt::begin_panic_fmt(&format_args!($fmt, $($arg)+), - &(file!(), line!(), __rust_unstable_column!())) + $crate::rt::begin_panic_fmt(&$crate::format_args!($fmt, $($arg)+), + &($crate::file!(), $crate::line!(), $crate::column!())) }); } @@ -113,7 +113,7 @@ macro_rules! panic { #[stable(feature = "rust1", since = "1.0.0")] #[allow_internal_unstable(print_internals)] macro_rules! print { - ($($arg:tt)*) => ($crate::io::_print(format_args!($($arg)*))); + ($($arg:tt)*) => ($crate::io::_print($crate::format_args!($($arg)*))); } /// Prints to the standard output, with a newline. @@ -147,7 +147,7 @@ macro_rules! print { macro_rules! println { () => ($crate::print!("\n")); ($($arg:tt)*) => ({ - $crate::io::_print(format_args_nl!($($arg)*)); + $crate::io::_print($crate::format_args_nl!($($arg)*)); }) } @@ -176,7 +176,7 @@ macro_rules! println { #[stable(feature = "eprint", since = "1.19.0")] #[allow_internal_unstable(print_internals)] macro_rules! eprint { - ($($arg:tt)*) => ($crate::io::_eprint(format_args!($($arg)*))); + ($($arg:tt)*) => ($crate::io::_eprint($crate::format_args!($($arg)*))); } /// Prints to the standard error, with a newline. @@ -206,7 +206,7 @@ macro_rules! eprint { macro_rules! eprintln { () => ($crate::eprint!("\n")); ($($arg:tt)*) => ({ - $crate::io::_eprint(format_args_nl!($($arg)*)); + $crate::io::_eprint($crate::format_args_nl!($($arg)*)); }) } @@ -337,7 +337,7 @@ macro_rules! eprintln { #[stable(feature = "dbg_macro", since = "1.32.0")] macro_rules! dbg { () => { - $crate::eprintln!("[{}:{}]", file!(), line!()); + $crate::eprintln!("[{}:{}]", $crate::file!(), $crate::line!()); }; ($val:expr) => { // Use of `match` here is intentional because it affects the lifetimes @@ -345,7 +345,7 @@ macro_rules! dbg { match $val { tmp => { $crate::eprintln!("[{}:{}] {} = {:#?}", - file!(), line!(), stringify!($val), &tmp); + $crate::file!(), $crate::line!(), $crate::stringify!($val), &tmp); tmp } } diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs index cdffa390223..d8b6fb6da93 100644 --- a/src/libstd/net/tcp.rs +++ b/src/libstd/net/tcp.rs @@ -1597,7 +1597,8 @@ mod tests { // FIXME: re-enabled openbsd tests once their socket timeout code // no longer has rounding errors. - #[cfg_attr(any(target_os = "netbsd", target_os = "openbsd"), ignore)] + // VxWorks ignores SO_SNDTIMEO. + #[cfg_attr(any(target_os = "netbsd", target_os = "openbsd", target_os = "vxworks"), ignore)] #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 #[test] fn timeouts() { diff --git a/src/libstd/net/udp.rs b/src/libstd/net/udp.rs index c430e103951..a5e7cd992f2 100644 --- a/src/libstd/net/udp.rs +++ b/src/libstd/net/udp.rs @@ -1026,7 +1026,8 @@ mod tests { // FIXME: re-enabled openbsd/netbsd tests once their socket timeout code // no longer has rounding errors. - #[cfg_attr(any(target_os = "netbsd", target_os = "openbsd"), ignore)] + // VxWorks ignores SO_SNDTIMEO. + #[cfg_attr(any(target_os = "netbsd", target_os = "openbsd", target_os = "vxworks"), ignore)] #[test] fn timeouts() { let addr = next_test_ip4(); diff --git a/src/libstd/os/raw/mod.rs b/src/libstd/os/raw/mod.rs index 0761c50f4b2..611a1709c8d 100644 --- a/src/libstd/os/raw/mod.rs +++ b/src/libstd/os/raw/mod.rs @@ -8,8 +8,7 @@ #![stable(feature = "raw_os", since = "1.1.0")] -#[cfg_attr(bootstrap, doc(include = "os/raw/char.md"))] -#[cfg_attr(not(bootstrap), doc(include = "char.md"))] +#[doc(include = "char.md")] #[cfg(any(all(target_os = "linux", any(target_arch = "aarch64", target_arch = "arm", target_arch = "hexagon", @@ -33,8 +32,7 @@ target_arch = "powerpc")), all(target_os = "fuchsia", target_arch = "aarch64")))] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = u8; -#[cfg_attr(bootstrap, doc(include = "os/raw/char.md"))] -#[cfg_attr(not(bootstrap), doc(include = "char.md"))] +#[doc(include = "char.md")] #[cfg(not(any(all(target_os = "linux", any(target_arch = "aarch64", target_arch = "arm", target_arch = "hexagon", @@ -58,51 +56,37 @@ target_arch = "powerpc")), all(target_os = "fuchsia", target_arch = "aarch64"))))] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = i8; -#[cfg_attr(bootstrap, doc(include = "os/raw/schar.md"))] -#[cfg_attr(not(bootstrap), doc(include = "schar.md"))] +#[doc(include = "schar.md")] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_schar = i8; -#[cfg_attr(bootstrap, doc(include = "os/raw/uchar.md"))] -#[cfg_attr(not(bootstrap), doc(include = "uchar.md"))] +#[doc(include = "uchar.md")] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_uchar = u8; -#[cfg_attr(bootstrap, doc(include = "os/raw/short.md"))] -#[cfg_attr(not(bootstrap), doc(include = "short.md"))] +#[doc(include = "short.md")] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_short = i16; -#[cfg_attr(bootstrap, doc(include = "os/raw/ushort.md"))] -#[cfg_attr(not(bootstrap), doc(include = "ushort.md"))] +#[doc(include = "ushort.md")] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_ushort = u16; -#[cfg_attr(bootstrap, doc(include = "os/raw/int.md"))] -#[cfg_attr(not(bootstrap), doc(include = "int.md"))] +#[doc(include = "int.md")] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_int = i32; -#[cfg_attr(bootstrap, doc(include = "os/raw/uint.md"))] -#[cfg_attr(not(bootstrap), doc(include = "uint.md"))] +#[doc(include = "uint.md")] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_uint = u32; -#[cfg_attr(bootstrap, doc(include = "os/raw/long.md"))] -#[cfg_attr(not(bootstrap), doc(include = "long.md"))] +#[doc(include = "long.md")] #[cfg(any(target_pointer_width = "32", windows))] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_long = i32; -#[cfg_attr(bootstrap, doc(include = "os/raw/ulong.md"))] -#[cfg_attr(not(bootstrap), doc(include = "ulong.md"))] +#[doc(include = "ulong.md")] #[cfg(any(target_pointer_width = "32", windows))] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulong = u32; -#[cfg_attr(bootstrap, doc(include = "os/raw/long.md"))] -#[cfg_attr(not(bootstrap), doc(include = "long.md"))] +#[doc(include = "long.md")] #[cfg(all(target_pointer_width = "64", not(windows)))] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_long = i64; -#[cfg_attr(bootstrap, doc(include = "os/raw/ulong.md"))] -#[cfg_attr(not(bootstrap), doc(include = "ulong.md"))] +#[doc(include = "ulong.md")] #[cfg(all(target_pointer_width = "64", not(windows)))] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulong = u64; -#[cfg_attr(bootstrap, doc(include = "os/raw/longlong.md"))] -#[cfg_attr(not(bootstrap), doc(include = "longlong.md"))] +#[doc(include = "longlong.md")] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_longlong = i64; -#[cfg_attr(bootstrap, doc(include = "os/raw/ulonglong.md"))] -#[cfg_attr(not(bootstrap), doc(include = "ulonglong.md"))] +#[doc(include = "ulonglong.md")] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulonglong = u64; -#[cfg_attr(bootstrap, doc(include = "os/raw/float.md"))] -#[cfg_attr(not(bootstrap), doc(include = "float.md"))] +#[doc(include = "float.md")] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_float = f32; -#[cfg_attr(bootstrap, doc(include = "os/raw/double.md"))] -#[cfg_attr(not(bootstrap), doc(include = "double.md"))] +#[doc(include = "double.md")] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_double = f64; #[stable(feature = "raw_os", since = "1.1.0")] diff --git a/src/libstd/prelude/v1.rs b/src/libstd/prelude/v1.rs index 1c61f21f7df..3e4cf91127f 100644 --- a/src/libstd/prelude/v1.rs +++ b/src/libstd/prelude/v1.rs @@ -7,10 +7,6 @@ #![stable(feature = "rust1", since = "1.0.0")] // Re-exported core operators -#[cfg(bootstrap)] -#[stable(feature = "rust1", since = "1.0.0")] -#[doc(no_inline)] -pub use crate::marker::Copy; #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use crate::marker::{Send, Sized, Sync, Unpin}; @@ -24,21 +20,9 @@ pub use crate::ops::{Drop, Fn, FnMut, FnOnce}; pub use crate::mem::drop; // Re-exported types and traits -#[cfg(bootstrap)] -#[stable(feature = "rust1", since = "1.0.0")] -#[doc(no_inline)] -pub use crate::clone::Clone; -#[cfg(bootstrap)] -#[stable(feature = "rust1", since = "1.0.0")] -#[doc(no_inline)] -pub use crate::cmp::{PartialEq, PartialOrd, Eq, Ord}; #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use crate::convert::{AsRef, AsMut, Into, From}; -#[cfg(bootstrap)] -#[stable(feature = "rust1", since = "1.0.0")] -#[doc(no_inline)] -pub use crate::default::Default; #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use crate::iter::{Iterator, Extend, IntoIterator}; @@ -53,11 +37,9 @@ pub use crate::option::Option::{self, Some, None}; pub use crate::result::Result::{self, Ok, Err}; // Re-exported built-in macros -#[cfg(not(bootstrap))] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[doc(no_inline)] pub use core::prelude::v1::{ - __rust_unstable_column, asm, assert, cfg, @@ -83,7 +65,6 @@ pub use core::prelude::v1::{ // FIXME: Attribute and derive macros are not documented because for them rustdoc generates // dead links which fail link checker testing. -#[cfg(not(bootstrap))] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow(deprecated)] #[doc(hidden)] diff --git a/src/libstd/sync/mod.rs b/src/libstd/sync/mod.rs index e29faf18d83..fd6e46fd61d 100644 --- a/src/libstd/sync/mod.rs +++ b/src/libstd/sync/mod.rs @@ -163,7 +163,6 @@ pub use self::condvar::{Condvar, WaitTimeoutResult}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::mutex::{Mutex, MutexGuard}; #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(bootstrap, allow(deprecated_in_future))] #[allow(deprecated)] pub use self::once::{Once, OnceState, ONCE_INIT}; #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/sys/cloudabi/abi/cloudabi.rs b/src/libstd/sys/cloudabi/abi/cloudabi.rs index 9addba8b611..38db4dd5165 100644 --- a/src/libstd/sys/cloudabi/abi/cloudabi.rs +++ b/src/libstd/sys/cloudabi/abi/cloudabi.rs @@ -115,6 +115,7 @@ #![no_std] #![allow(non_camel_case_types)] +#![allow(deprecated)] // FIXME: using `mem::uninitialized()` include!("bitflags.rs"); diff --git a/src/libstd/sys/cloudabi/mod.rs b/src/libstd/sys/cloudabi/mod.rs index 6e147612eb4..2fb10cc370a 100644 --- a/src/libstd/sys/cloudabi/mod.rs +++ b/src/libstd/sys/cloudabi/mod.rs @@ -1,5 +1,3 @@ -#![allow(deprecated_in_future)] // mem::uninitialized; becomes `deprecated` when nightly is 1.39 - use crate::io::ErrorKind; use crate::mem; diff --git a/src/libstd/sys/cloudabi/mutex.rs b/src/libstd/sys/cloudabi/mutex.rs index d3ff0077b20..0e30d3a1c6c 100644 --- a/src/libstd/sys/cloudabi/mutex.rs +++ b/src/libstd/sys/cloudabi/mutex.rs @@ -104,10 +104,11 @@ impl ReentrantMutex { }, ..mem::zeroed() }; - let mut event: abi::event = mem::uninitialized(); - let mut nevents: usize = mem::uninitialized(); - let ret = abi::poll(&subscription, &mut event, 1, &mut nevents); + let mut event = MaybeUninit::<abi::event>::uninit(); + let mut nevents = MaybeUninit::<usize>::uninit(); + let ret = abi::poll(&subscription, event.as_mut_ptr(), 1, nevents.as_mut_ptr()); assert_eq!(ret, abi::errno::SUCCESS, "Failed to acquire mutex"); + let event = event.assume_init(); assert_eq!(event.error, abi::errno::SUCCESS, "Failed to acquire mutex"); } } diff --git a/src/libstd/sys/cloudabi/rwlock.rs b/src/libstd/sys/cloudabi/rwlock.rs index 6da3f3841b6..73499d65a06 100644 --- a/src/libstd/sys/cloudabi/rwlock.rs +++ b/src/libstd/sys/cloudabi/rwlock.rs @@ -1,5 +1,6 @@ use crate::cell::UnsafeCell; use crate::mem; +use crate::mem::MaybeUninit; use crate::sync::atomic::{AtomicU32, Ordering}; use crate::sys::cloudabi::abi; @@ -73,10 +74,11 @@ impl RWLock { }, ..mem::zeroed() }; - let mut event: abi::event = mem::uninitialized(); - let mut nevents: usize = mem::uninitialized(); - let ret = abi::poll(&subscription, &mut event, 1, &mut nevents); + let mut event = MaybeUninit::<abi::event>::uninit(); + let mut nevents = MaybeUninit::<usize>::uninit(); + let ret = abi::poll(&subscription, event.as_mut_ptr(), 1, nevents.as_mut_ptr()); assert_eq!(ret, abi::errno::SUCCESS, "Failed to acquire read lock"); + let event = event.assume_init(); assert_eq!( event.error, abi::errno::SUCCESS, @@ -182,10 +184,11 @@ impl RWLock { }, ..mem::zeroed() }; - let mut event: abi::event = mem::uninitialized(); - let mut nevents: usize = mem::uninitialized(); - let ret = abi::poll(&subscription, &mut event, 1, &mut nevents); + let mut event = MaybeUninit::<abi::event>::uninit(); + let mut nevents = MaybeUninit::<usize>::uninit(); + let ret = abi::poll(&subscription, event.as_mut_ptr(), 1, nevents.as_mut_ptr()); assert_eq!(ret, abi::errno::SUCCESS, "Failed to acquire write lock"); + let event = event.assume_init(); assert_eq!( event.error, abi::errno::SUCCESS, diff --git a/src/libstd/sys/cloudabi/thread.rs b/src/libstd/sys/cloudabi/thread.rs index 7da16c4d247..240b6ea9e57 100644 --- a/src/libstd/sys/cloudabi/thread.rs +++ b/src/libstd/sys/cloudabi/thread.rs @@ -72,10 +72,11 @@ impl Thread { }, ..mem::zeroed() }; - let mut event: abi::event = mem::uninitialized(); - let mut nevents: usize = mem::uninitialized(); - let ret = abi::poll(&subscription, &mut event, 1, &mut nevents); + let mut event = mem::MaybeUninit::<abi::event>::uninit(); + let mut nevents = mem::MaybeUninit::<usize>::uninit(); + let ret = abi::poll(&subscription, event.as_mut_ptr(), 1, nevents.as_mut_ptr()); assert_eq!(ret, abi::errno::SUCCESS); + let event = event.assume_init(); assert_eq!(event.error, abi::errno::SUCCESS); } } diff --git a/src/libstd/sys/unix/process/process_common.rs b/src/libstd/sys/unix/process/process_common.rs index 6bb20bbe087..21fca23a8fe 100644 --- a/src/libstd/sys/unix/process/process_common.rs +++ b/src/libstd/sys/unix/process/process_common.rs @@ -20,6 +20,30 @@ cfg_if::cfg_if! { } } +// Android with api less than 21 define sig* functions inline, so it is not +// available for dynamic link. Implementing sigemptyset and sigaddset allow us +// to support older Android version (independent of libc version). +// The following implementations are based on https://git.io/vSkNf +cfg_if::cfg_if! { + if #[cfg(target_os = "android")] { + pub unsafe fn sigemptyset(set: *mut libc::sigset_t) -> libc::c_int { + set.write_bytes(0u8, 1); + return 0; + } + #[allow(dead_code)] + pub unsafe fn sigaddset(set: *mut libc::sigset_t, signum: libc::c_int) -> libc::c_int { + use crate::{slice, mem}; + + let raw = slice::from_raw_parts_mut(set as *mut u8, mem::size_of::<libc::sigset_t>()); + let bit = (signum - 1) as usize; + raw[bit / 8] |= 1 << (bit % 8); + return 0; + } + } else { + pub use libc::{sigemptyset, sigaddset}; + } +} + //////////////////////////////////////////////////////////////////////////////// // Command //////////////////////////////////////////////////////////////////////////////// @@ -429,36 +453,6 @@ mod tests { } } - // Android with api less than 21 define sig* functions inline, so it is not - // available for dynamic link. Implementing sigemptyset and sigaddset allow us - // to support older Android version (independent of libc version). - // The following implementations are based on https://git.io/vSkNf - - #[cfg(not(target_os = "android"))] - extern { - #[cfg_attr(target_os = "netbsd", link_name = "__sigemptyset14")] - fn sigemptyset(set: *mut libc::sigset_t) -> libc::c_int; - - #[cfg_attr(target_os = "netbsd", link_name = "__sigaddset14")] - fn sigaddset(set: *mut libc::sigset_t, signum: libc::c_int) -> libc::c_int; - } - - #[cfg(target_os = "android")] - unsafe fn sigemptyset(set: *mut libc::sigset_t) -> libc::c_int { - set.write_bytes(0u8, 1); - return 0; - } - - #[cfg(target_os = "android")] - unsafe fn sigaddset(set: *mut libc::sigset_t, signum: libc::c_int) -> libc::c_int { - use crate::slice; - - let raw = slice::from_raw_parts_mut(set as *mut u8, mem::size_of::<libc::sigset_t>()); - let bit = (signum - 1) as usize; - raw[bit / 8] |= 1 << (bit % 8); - return 0; - } - // See #14232 for more information, but it appears that signal delivery to a // newly spawned process may just be raced in the macOS, so to prevent this // test from being flaky we ignore it on macOS. diff --git a/src/libstd/sys/unix/process/process_unix.rs b/src/libstd/sys/unix/process/process_unix.rs index 327d82e60cf..a9711c71b7a 100644 --- a/src/libstd/sys/unix/process/process_unix.rs +++ b/src/libstd/sys/unix/process/process_unix.rs @@ -214,14 +214,7 @@ impl Command { // need to clean things up now to avoid confusing the program // we're about to run. let mut set = MaybeUninit::<libc::sigset_t>::uninit(); - if cfg!(target_os = "android") { - // Implementing sigemptyset allow us to support older Android - // versions. See the comment about Android and sig* functions in - // process_common.rs - set.as_mut_ptr().write_bytes(0u8, 1); - } else { - cvt(libc::sigemptyset(set.as_mut_ptr()))?; - } + cvt(sigemptyset(set.as_mut_ptr()))?; cvt(libc::pthread_sigmask(libc::SIG_SETMASK, set.as_ptr(), ptr::null_mut()))?; let ret = sys::signal(libc::SIGPIPE, libc::SIG_DFL); @@ -363,10 +356,10 @@ impl Command { } let mut set = MaybeUninit::<libc::sigset_t>::uninit(); - cvt(libc::sigemptyset(set.as_mut_ptr()))?; + cvt(sigemptyset(set.as_mut_ptr()))?; cvt(libc::posix_spawnattr_setsigmask(attrs.0.as_mut_ptr(), set.as_ptr()))?; - cvt(libc::sigaddset(set.as_mut_ptr(), libc::SIGPIPE))?; + cvt(sigaddset(set.as_mut_ptr(), libc::SIGPIPE))?; cvt(libc::posix_spawnattr_setsigdefault(attrs.0.as_mut_ptr(), set.as_ptr()))?; diff --git a/src/libstd/sys/vxworks/process/process_common.rs b/src/libstd/sys/vxworks/process/process_common.rs index 397200c39c2..ba797354a73 100644 --- a/src/libstd/sys/vxworks/process/process_common.rs +++ b/src/libstd/sys/vxworks/process/process_common.rs @@ -155,7 +155,7 @@ impl Command { _f: Box<dyn FnMut() -> io::Result<()> + Send + Sync>, ) { // Fork() is not supported in vxWorks so no way to run the closure in the new procecss. - unimplemented!();; + unimplemented!(); } pub fn stdin(&mut self, stdin: Stdio) { diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index f706709c9cc..b1f9d9766f7 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -714,7 +714,7 @@ if #[cfg(target_vendor = "uwp")] { pub struct FILE_STANDARD_INFO { pub AllocationSize: LARGE_INTEGER, pub EndOfFile: LARGE_INTEGER, - pub NumberOfLink: DWORD, + pub NumberOfLinks: DWORD, pub DeletePending: BOOLEAN, pub Directory: BOOLEAN, } diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index 5bae6ba4749..204f6af5fc1 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -357,7 +357,7 @@ impl File { size as c::DWORD))?; attr.file_size = info.AllocationSize as u64; attr.number_of_links = Some(info.NumberOfLinks); - if attr.is_reparse_point() { + if attr.file_type().is_reparse_point() { let mut b = [0; c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; if let Ok((_, buf)) = self.reparse_point(&mut b) { attr.reparse_tag = buf.ReparseTag; diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 052eb55b408..50e428ea0cc 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -5,7 +5,7 @@ pub use UnsafeSource::*; pub use crate::symbol::{Ident, Symbol as Name}; pub use crate::util::parser::ExprPrecedence; -use crate::ext::hygiene::{ExpnId, SyntaxContext}; +use crate::ext::hygiene::ExpnId; use crate::parse::token::{self, DelimToken}; use crate::print::pprust; use crate::ptr::P; @@ -571,10 +571,11 @@ impl Pat { match &self.node { PatKind::Ident(_, _, Some(p)) => p.walk(it), - PatKind::Struct(_, fields, _) => fields.iter().all(|field| field.node.pat.walk(it)), - PatKind::TupleStruct(_, s) | PatKind::Tuple(s) | PatKind::Slice(s) => { - s.iter().all(|p| p.walk(it)) - } + PatKind::Struct(_, fields, _) => fields.iter().all(|field| field.pat.walk(it)), + PatKind::TupleStruct(_, s) + | PatKind::Tuple(s) + | PatKind::Slice(s) + | PatKind::Or(s) => s.iter().all(|p| p.walk(it)), PatKind::Box(s) | PatKind::Ref(s, _) | PatKind::Paren(s) => s.walk(it), PatKind::Wild | PatKind::Rest @@ -608,6 +609,8 @@ pub struct FieldPat { pub pat: P<Pat>, pub is_shorthand: bool, pub attrs: ThinVec<Attribute>, + pub id: NodeId, + pub span: Span, } #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)] @@ -641,11 +644,15 @@ pub enum PatKind { /// A struct or struct variant pattern (e.g., `Variant {x, y, ..}`). /// The `bool` is `true` in the presence of a `..`. - Struct(Path, Vec<Spanned<FieldPat>>, /* recovered */ bool), + Struct(Path, Vec<FieldPat>, /* recovered */ bool), /// A tuple struct/variant pattern (`Variant(x, y, .., z)`). TupleStruct(Path, Vec<P<Pat>>), + /// An or-pattern `A | B | C`. + /// Invariant: `pats.len() >= 2`. + Or(Vec<P<Pat>>), + /// A possibly qualified path pattern. /// Unqualified path patterns `A::B::C` can legally refer to variants, structs, constants /// or associated constants. Qualified path patterns `<A>::B::C`/`<A as Trait>::B::C` can @@ -925,6 +932,7 @@ pub struct Arm { pub guard: Option<P<Expr>>, pub body: P<Expr>, pub span: Span, + pub id: NodeId, } #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] @@ -934,10 +942,9 @@ pub struct Field { pub span: Span, pub is_shorthand: bool, pub attrs: ThinVec<Attribute>, + pub id: NodeId, } -pub type SpannedIdent = Spanned<Ident>; - #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)] pub enum BlockCheckMode { Default, @@ -1284,8 +1291,6 @@ pub enum Movability { Movable, } -pub type Mac = Spanned<Mac_>; - /// Represents a macro invocation. The `Path` indicates which macro /// is being invoked, and the vector of token-trees contains the source /// of the macro invocation. @@ -1293,10 +1298,11 @@ pub type Mac = Spanned<Mac_>; /// N.B., the additional ident for a `macro_rules`-style macro is actually /// stored in the enclosing item. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct Mac_ { +pub struct Mac { pub path: Path, pub delim: MacDelimiter, pub tts: TokenStream, + pub span: Span, pub prior_type_ascription: Option<(Span, bool)>, } @@ -1307,7 +1313,7 @@ pub enum MacDelimiter { Brace, } -impl Mac_ { +impl Mac { pub fn stream(&self) -> TokenStream { self.tts.clone() } @@ -1781,7 +1787,6 @@ pub struct InlineAsm { pub volatile: bool, pub alignstack: bool, pub dialect: AsmDialect, - pub ctxt: SyntaxContext, } /// An argument in a function header. @@ -2029,7 +2034,6 @@ pub struct ForeignMod { #[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy)] pub struct GlobalAsm { pub asm: Symbol, - pub ctxt: SyntaxContext, } #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] @@ -2038,7 +2042,7 @@ pub struct EnumDef { } #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct Variant_ { +pub struct Variant { /// Name of the variant. pub ident: Ident, /// Attributes of the variant. @@ -2049,10 +2053,10 @@ pub struct Variant_ { pub data: VariantData, /// Explicit discriminant, e.g., `Foo = 1`. pub disr_expr: Option<AnonConst>, + /// Span + pub span: Span, } -pub type Variant = Spanned<Variant_>; - /// Part of `use` item to the right of its prefix. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum UseTreeKind { diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs index a9d3227b3a8..bcf03b5237a 100644 --- a/src/libsyntax/attr/mod.rs +++ b/src/libsyntax/attr/mod.rs @@ -13,7 +13,7 @@ use crate::ast::{AttrId, AttrStyle, Name, Ident, Path, PathSegment}; use crate::ast::{MetaItem, MetaItemKind, NestedMetaItem}; use crate::ast::{Lit, LitKind, Expr, Item, Local, Stmt, StmtKind, GenericParam}; use crate::mut_visit::visit_clobber; -use crate::source_map::{BytePos, Spanned, dummy_spanned}; +use crate::source_map::{BytePos, Spanned, DUMMY_SP}; use crate::parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration}; use crate::parse::parser::Parser; use crate::parse::{self, ParseSess, PResult}; @@ -327,8 +327,10 @@ impl Attribute { if self.is_sugared_doc { let comment = self.value_str().unwrap(); let meta = mk_name_value_item_str( - Ident::with_empty_ctxt(sym::doc), - dummy_spanned(Symbol::intern(&strip_doc_comment_decoration(&comment.as_str())))); + Ident::with_dummy_span(sym::doc), + Symbol::intern(&strip_doc_comment_decoration(&comment.as_str())), + DUMMY_SP, + ); f(&Attribute { id: self.id, style: self.style, @@ -345,9 +347,9 @@ impl Attribute { /* Constructors */ -pub fn mk_name_value_item_str(ident: Ident, value: Spanned<Symbol>) -> MetaItem { - let lit_kind = LitKind::Str(value.node, ast::StrStyle::Cooked); - mk_name_value_item(ident, lit_kind, value.span) +pub fn mk_name_value_item_str(ident: Ident, str: Symbol, str_span: Span) -> MetaItem { + let lit_kind = LitKind::Str(str, ast::StrStyle::Cooked); + mk_name_value_item(ident, lit_kind, str_span) } pub fn mk_name_value_item(ident: Ident, lit_kind: LitKind, lit_span: Span) -> MetaItem { @@ -410,7 +412,7 @@ pub fn mk_sugared_doc_attr(text: Symbol, span: Span) -> Attribute { Attribute { id: mk_attr_id(), style, - path: Path::from_ident(Ident::with_empty_ctxt(sym::doc).with_span_pos(span)), + path: Path::from_ident(Ident::with_dummy_span(sym::doc).with_span_pos(span)), tokens: MetaItemKind::NameValue(lit).tokens(span), is_sugared_doc: true, span, @@ -712,7 +714,7 @@ macro_rules! derive_has_attrs { derive_has_attrs! { Item, Expr, Local, ast::ForeignItem, ast::StructField, ast::ImplItem, ast::TraitItem, ast::Arm, - ast::Field, ast::FieldPat, ast::Variant_, ast::Arg + ast::Field, ast::FieldPat, ast::Variant, ast::Arg } pub fn inject(mut krate: ast::Crate, parse_sess: &ParseSess, attrs: &[String]) -> ast::Crate { diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index 1ab367f73c1..7eeea4e7bdf 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -260,7 +260,7 @@ impl<'a> StripUnconfigured<'a> { ast::ItemKind::Enum(ast::EnumDef { variants }, _generics) => { variants.flat_map_in_place(|variant| self.configure(variant)); for variant in variants { - self.configure_variant_data(&mut variant.node.data); + self.configure_variant_data(&mut variant.data); } } _ => {} diff --git a/src/libsyntax/diagnostics/plugin.rs b/src/libsyntax/diagnostics/plugin.rs index 80591ad304d..9618b5acfb0 100644 --- a/src/libsyntax/diagnostics/plugin.rs +++ b/src/libsyntax/diagnostics/plugin.rs @@ -172,7 +172,7 @@ pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt<'_>, (descriptions.len(), ecx.expr_vec(span, descriptions)) }); - let static_ = ecx.lifetime(span, Ident::with_empty_ctxt(kw::StaticLifetime)); + let static_ = ecx.lifetime(span, Ident::with_dummy_span(kw::StaticLifetime)); let ty_str = ecx.ty_rptr( span, ecx.ty_ident(span, ecx.ident_of("str")), diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 7f4feff6be6..b0a4a6af983 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -1,6 +1,6 @@ -use crate::ast::{self, Attribute, Name, PatKind}; +use crate::ast::{self, NodeId, Attribute, Name, PatKind}; use crate::attr::{HasAttrs, Stability, Deprecation}; -use crate::source_map::{SourceMap, Spanned, respan}; +use crate::source_map::SourceMap; use crate::edition::Edition; use crate::ext::expand::{self, AstFragment, Invocation}; use crate::ext::hygiene::{ExpnId, SyntaxContext, Transparency}; @@ -15,7 +15,7 @@ use crate::tokenstream::{self, TokenStream, TokenTree}; use errors::{DiagnosticBuilder, DiagnosticId}; use smallvec::{smallvec, SmallVec}; use syntax_pos::{FileName, Span, MultiSpan, DUMMY_SP}; -use syntax_pos::hygiene::{ExpnInfo, ExpnKind}; +use syntax_pos::hygiene::{ExpnData, ExpnKind}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::{self, Lrc}; @@ -405,7 +405,6 @@ impl MacResult for MacEager { /// after hitting errors. #[derive(Copy, Clone)] pub struct DummyResult { - expr_only: bool, is_error: bool, span: Span, } @@ -416,21 +415,12 @@ impl DummyResult { /// Use this as a return value after hitting any errors and /// calling `span_err`. pub fn any(span: Span) -> Box<dyn MacResult+'static> { - Box::new(DummyResult { expr_only: false, is_error: true, span }) + Box::new(DummyResult { is_error: true, span }) } /// Same as `any`, but must be a valid fragment, not error. pub fn any_valid(span: Span) -> Box<dyn MacResult+'static> { - Box::new(DummyResult { expr_only: false, is_error: false, span }) - } - - /// Creates a default MacResult that can only be an expression. - /// - /// Use this for macros that must expand to an expression, so even - /// if an error is encountered internally, the user will receive - /// an error that they also used it in the wrong place. - pub fn expr(span: Span) -> Box<dyn MacResult+'static> { - Box::new(DummyResult { expr_only: true, is_error: true, span }) + Box::new(DummyResult { is_error: false, span }) } /// A plain dummy expression. @@ -472,36 +462,19 @@ impl MacResult for DummyResult { } fn make_items(self: Box<DummyResult>) -> Option<SmallVec<[P<ast::Item>; 1]>> { - // this code needs a comment... why not always just return the Some() ? - if self.expr_only { - None - } else { - Some(SmallVec::new()) - } + Some(SmallVec::new()) } fn make_impl_items(self: Box<DummyResult>) -> Option<SmallVec<[ast::ImplItem; 1]>> { - if self.expr_only { - None - } else { - Some(SmallVec::new()) - } + Some(SmallVec::new()) } fn make_trait_items(self: Box<DummyResult>) -> Option<SmallVec<[ast::TraitItem; 1]>> { - if self.expr_only { - None - } else { - Some(SmallVec::new()) - } + Some(SmallVec::new()) } fn make_foreign_items(self: Box<Self>) -> Option<SmallVec<[ast::ForeignItem; 1]>> { - if self.expr_only { - None - } else { - Some(SmallVec::new()) - } + Some(SmallVec::new()) } fn make_stmts(self: Box<DummyResult>) -> Option<SmallVec<[ast::Stmt; 1]>> { @@ -667,10 +640,11 @@ impl SyntaxExtension { SyntaxExtension::default(SyntaxExtensionKind::NonMacroAttr { mark_used }, edition) } - pub fn expn_info(&self, call_site: Span, descr: Symbol) -> ExpnInfo { - ExpnInfo { - call_site, + pub fn expn_data(&self, parent: ExpnId, call_site: Span, descr: Symbol) -> ExpnData { + ExpnData { kind: ExpnKind::Macro(self.macro_kind(), descr), + parent, + call_site, def_site: self.span, default_transparency: self.default_transparency, allow_internal_unstable: self.allow_internal_unstable.clone(), @@ -697,13 +671,13 @@ bitflags::bitflags! { } pub trait Resolver { - fn next_node_id(&mut self) -> ast::NodeId; + fn next_node_id(&mut self) -> NodeId; - fn get_module_scope(&mut self, id: ast::NodeId) -> ExpnId; + fn get_module_scope(&mut self, id: NodeId) -> ExpnId; fn resolve_dollar_crates(&mut self); fn visit_ast_fragment_with_placeholders(&mut self, expn_id: ExpnId, fragment: &AstFragment, - derives: &[ExpnId]); + extra_placeholders: &[NodeId]); fn register_builtin_macro(&mut self, ident: ast::Ident, ext: SyntaxExtension); fn resolve_imports(&mut self); @@ -734,7 +708,7 @@ pub struct ExpansionData { /// One of these is made during expansion and incrementally updated as we go; /// when a macro expansion occurs, the resulting nodes have the `backtrace() -/// -> expn_info` of their expansion context stored into their span. +/// -> expn_data` of their expansion context stored into their span. pub struct ExtCtxt<'a> { pub parse_sess: &'a parse::ParseSess, pub ecfg: expand::ExpansionConfig<'a>, @@ -783,13 +757,10 @@ impl<'a> ExtCtxt<'a> { pub fn parse_sess(&self) -> &'a parse::ParseSess { self.parse_sess } pub fn cfg(&self) -> &ast::CrateConfig { &self.parse_sess.config } pub fn call_site(&self) -> Span { - match self.current_expansion.id.expn_info() { - Some(expn_info) => expn_info.call_site, - None => DUMMY_SP, - } + self.current_expansion.id.expn_data().call_site } pub fn backtrace(&self) -> SyntaxContext { - SyntaxContext::empty().apply_mark(self.current_expansion.id) + SyntaxContext::root().apply_mark(self.current_expansion.id) } /// Returns span for the macro which originally caused the current expansion to happen. @@ -799,17 +770,13 @@ impl<'a> ExtCtxt<'a> { let mut ctxt = self.backtrace(); let mut last_macro = None; loop { - if ctxt.outer_expn_info().map_or(None, |info| { - if info.kind.descr() == sym::include { - // Stop going up the backtrace once include! is encountered - return None; - } - ctxt = info.call_site.ctxt(); - last_macro = Some(info.call_site); - Some(()) - }).is_none() { - break + let expn_data = ctxt.outer_expn_data(); + // Stop going up the backtrace once include! is encountered + if expn_data.is_root() || expn_data.kind.descr() == sym::include { + break; } + ctxt = expn_data.call_site.ctxt(); + last_macro = Some(expn_data.call_site); } last_macro } @@ -899,7 +866,7 @@ impl<'a> ExtCtxt<'a> { pub fn std_path(&self, components: &[Symbol]) -> Vec<ast::Ident> { let def_site = DUMMY_SP.apply_mark(self.current_expansion.id); iter::once(Ident::new(kw::DollarCrate, def_site)) - .chain(components.iter().map(|&s| Ident::with_empty_ctxt(s))) + .chain(components.iter().map(|&s| Ident::with_dummy_span(s))) .collect() } pub fn name_of(&self, st: &str) -> ast::Name { @@ -943,15 +910,17 @@ pub fn expr_to_spanned_string<'a>( cx: &'a mut ExtCtxt<'_>, mut expr: P<ast::Expr>, err_msg: &str, -) -> Result<Spanned<(Symbol, ast::StrStyle)>, Option<DiagnosticBuilder<'a>>> { +) -> Result<(Symbol, ast::StrStyle, Span), Option<DiagnosticBuilder<'a>>> { // Update `expr.span`'s ctxt now in case expr is an `include!` macro invocation. expr.span = expr.span.apply_mark(cx.current_expansion.id); - // we want to be able to handle e.g., `concat!("foo", "bar")` - cx.expander().visit_expr(&mut expr); + // Perform eager expansion on the expression. + // We want to be able to handle e.g., `concat!("foo", "bar")`. + let expr = cx.expander().fully_expand_fragment(AstFragment::Expr(expr)).make_expr(); + Err(match expr.node { ast::ExprKind::Lit(ref l) => match l.node { - ast::LitKind::Str(s, style) => return Ok(respan(expr.span, (s, style))), + ast::LitKind::Str(s, style) => return Ok((s, style, expr.span)), ast::LitKind::Err(_) => None, _ => Some(cx.struct_span_err(l.span, err_msg)) }, @@ -965,7 +934,7 @@ pub fn expr_to_string(cx: &mut ExtCtxt<'_>, expr: P<ast::Expr>, err_msg: &str) expr_to_spanned_string(cx, expr, err_msg) .map_err(|err| err.map(|mut err| err.emit())) .ok() - .map(|s| s.node) + .map(|(symbol, style, _)| (symbol, style)) } /// Non-fatally assert that `tts` is empty. Note that this function @@ -1013,8 +982,12 @@ pub fn get_exprs_from_tts(cx: &mut ExtCtxt<'_>, let mut p = cx.new_parser_from_tts(tts); let mut es = Vec::new(); while p.token != token::Eof { - let mut expr = panictry!(p.parse_expr()); - cx.expander().visit_expr(&mut expr); + let expr = panictry!(p.parse_expr()); + + // Perform eager expansion on the expression. + // We want to be able to handle e.g., `concat!("foo", "bar")`. + let expr = cx.expander().fully_expand_fragment(AstFragment::Expr(expr)).make_expr(); + es.push(expr); if p.eat(&token::Comma) { continue; diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 22962499a2b..e2ac4d573a1 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -340,7 +340,7 @@ impl<'a> ExtCtxt<'a> { self.expr_path(self.path_ident(span, id)) } pub fn expr_self(&self, span: Span) -> P<ast::Expr> { - self.expr_ident(span, Ident::with_empty_ctxt(kw::SelfLower)) + self.expr_ident(span, Ident::with_dummy_span(kw::SelfLower)) } pub fn expr_binary(&self, sp: Span, op: ast::BinOpKind, @@ -403,6 +403,7 @@ impl<'a> ExtCtxt<'a> { span, is_shorthand: false, attrs: ThinVec::new(), + id: ast::DUMMY_NODE_ID, } } pub fn expr_struct( @@ -574,7 +575,7 @@ impl<'a> ExtCtxt<'a> { self.pat(span, PatKind::TupleStruct(path, subpats)) } pub fn pat_struct(&self, span: Span, path: ast::Path, - field_pats: Vec<Spanned<ast::FieldPat>>) -> P<ast::Pat> { + field_pats: Vec<ast::FieldPat>) -> P<ast::Pat> { self.pat(span, PatKind::Struct(path, field_pats, false)) } pub fn pat_tuple(&self, span: Span, pats: Vec<P<ast::Pat>>) -> P<ast::Pat> { @@ -612,6 +613,7 @@ impl<'a> ExtCtxt<'a> { guard: None, body: expr, span, + id: ast::DUMMY_NODE_ID, } } @@ -781,14 +783,14 @@ impl<'a> ExtCtxt<'a> { ast::VariantData::Tuple(fields, ast::DUMMY_NODE_ID) }; - respan(span, - ast::Variant_ { - ident, - id: ast::DUMMY_NODE_ID, - attrs: Vec::new(), - data: vdata, - disr_expr: None, - }) + ast::Variant { + attrs: Vec::new(), + data: vdata, + disr_expr: None, + id: ast::DUMMY_NODE_ID, + ident, + span, + } } pub fn item_enum_poly(&self, span: Span, name: Ident, diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 9a3195b1165..c1d52c97455 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -1,11 +1,11 @@ use crate::ast::{self, Block, Ident, LitKind, NodeId, PatKind, Path}; use crate::ast::{MacStmtStyle, StmtKind, ItemKind}; use crate::attr::{self, HasAttrs}; -use crate::source_map::{dummy_spanned, respan}; +use crate::source_map::respan; use crate::config::StripUnconfigured; use crate::ext::base::*; use crate::ext::proc_macro::collect_derives; -use crate::ext::hygiene::{ExpnId, SyntaxContext, ExpnInfo, ExpnKind}; +use crate::ext::hygiene::{ExpnId, SyntaxContext, ExpnData, ExpnKind}; use crate::ext::tt::macro_rules::annotate_err_with_kind; use crate::ext::placeholders::{placeholder, PlaceholderExpander}; use crate::feature_gate::{self, Features, GateIssue, is_builtin_attr, emit_feature_err}; @@ -25,7 +25,6 @@ use syntax_pos::{Span, DUMMY_SP, FileName}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; -use std::fs; use std::io::ErrorKind; use std::{iter, mem}; use std::ops::DerefMut; @@ -116,18 +115,6 @@ macro_rules! ast_fragments { } } - impl<'a, 'b> MutVisitor for MacroExpander<'a, 'b> { - fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> { - self.expand_fragment(AstFragment::OptExpr(Some(expr))).make_opt_expr() - } - $($(fn $mut_visit_ast(&mut self, ast: &mut $AstTy) { - visit_clobber(ast, |ast| self.expand_fragment(AstFragment::$Kind(ast)).$make_ast()); - })?)* - $($(fn $flat_map_ast_elt(&mut self, ast_elt: <$AstTy as IntoIterator>::Item) -> $AstTy { - self.expand_fragment(AstFragment::$Kind(smallvec![ast_elt])).$make_ast() - })?)* - } - impl<'a> MacResult for crate::ext::tt::macro_rules::ParserAnyMacro<'a> { $(fn $make_ast(self: Box<crate::ext::tt::macro_rules::ParserAnyMacro<'a>>) -> Option<$AstTy> { @@ -265,7 +252,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { tokens: None, })]); - match self.expand_fragment(krate_item).make_items().pop().map(P::into_inner) { + match self.fully_expand_fragment(krate_item).make_items().pop().map(P::into_inner) { Some(ast::Item { attrs, node: ast::ItemKind::Mod(module), .. }) => { krate.attrs = attrs; krate.module = module; @@ -285,8 +272,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> { krate } - // Fully expand all macro invocations in this AST fragment. - fn expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragment { + // Recursively expand all macro invocations in this AST fragment. + pub fn fully_expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragment { let orig_expansion_data = self.cx.current_expansion.clone(); self.cx.current_expansion.depth = 0; @@ -304,7 +291,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { // Unresolved macros produce dummy outputs as a recovery measure. invocations.reverse(); let mut expanded_fragments = Vec::new(); - let mut derives: FxHashMap<ExpnId, Vec<_>> = FxHashMap::default(); + let mut all_derive_placeholders: FxHashMap<ExpnId, Vec<_>> = FxHashMap::default(); let mut undetermined_invocations = Vec::new(); let (mut progress, mut force) = (false, !self.monotonic); loop { @@ -360,13 +347,14 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let mut item = self.fully_configure(item); item.visit_attrs(|attrs| attrs.retain(|a| a.path != sym::derive)); - let derives = derives.entry(invoc.expansion_data.id).or_default(); + let derive_placeholders = + all_derive_placeholders.entry(invoc.expansion_data.id).or_default(); - derives.reserve(traits.len()); + derive_placeholders.reserve(traits.len()); invocations.reserve(traits.len()); for path in traits { - let expn_id = ExpnId::fresh(self.cx.current_expansion.id, None); - derives.push(expn_id); + let expn_id = ExpnId::fresh(None); + derive_placeholders.push(NodeId::placeholder_from_expn_id(expn_id)); invocations.push(Invocation { kind: InvocationKind::Derive { path, item: item.clone() }, fragment_kind: invoc.fragment_kind, @@ -378,7 +366,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } let fragment = invoc.fragment_kind .expect_from_annotatables(::std::iter::once(item)); - self.collect_invocations(fragment, derives) + self.collect_invocations(fragment, derive_placeholders) } else { unreachable!() }; @@ -397,10 +385,11 @@ impl<'a, 'b> MacroExpander<'a, 'b> { // Finally incorporate all the expanded macros into the input AST fragment. let mut placeholder_expander = PlaceholderExpander::new(self.cx, self.monotonic); while let Some(expanded_fragments) = expanded_fragments.pop() { - for (mark, expanded_fragment) in expanded_fragments.into_iter().rev() { - let derives = derives.remove(&mark).unwrap_or_else(Vec::new); - placeholder_expander.add(NodeId::placeholder_from_expn_id(mark), - expanded_fragment, derives); + for (expn_id, expanded_fragment) in expanded_fragments.into_iter().rev() { + let derive_placeholders = + all_derive_placeholders.remove(&expn_id).unwrap_or_else(Vec::new); + placeholder_expander.add(NodeId::placeholder_from_expn_id(expn_id), + expanded_fragment, derive_placeholders); } } fragment_with_placeholders.mut_visit_with(&mut placeholder_expander); @@ -417,7 +406,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { /// them with "placeholders" - dummy macro invocations with specially crafted `NodeId`s. /// Then call into resolver that builds a skeleton ("reduced graph") of the fragment and /// prepares data for resolving paths of macro invocations. - fn collect_invocations(&mut self, mut fragment: AstFragment, derives: &[ExpnId]) + fn collect_invocations(&mut self, mut fragment: AstFragment, extra_placeholders: &[NodeId]) -> (AstFragment, Vec<Invocation>) { // Resolve `$crate`s in the fragment for pretty-printing. self.cx.resolver.resolve_dollar_crates(); @@ -436,9 +425,10 @@ impl<'a, 'b> MacroExpander<'a, 'b> { collector.invocations }; + // FIXME: Merge `extra_placeholders` into the `fragment` as regular placeholders. if self.monotonic { self.cx.resolver.visit_ast_fragment_with_placeholders( - self.cx.current_expansion.id, &fragment, derives); + self.cx.current_expansion.id, &fragment, extra_placeholders); } (fragment, invocations) @@ -487,11 +477,11 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } if self.cx.current_expansion.depth > self.cx.ecfg.recursion_limit { - let info = self.cx.current_expansion.id.expn_info().unwrap(); + let expn_data = self.cx.current_expansion.id.expn_data(); let suggested_limit = self.cx.ecfg.recursion_limit * 2; - let mut err = self.cx.struct_span_err(info.call_site, + let mut err = self.cx.struct_span_err(expn_data.call_site, &format!("recursion limit reached while expanding the macro `{}`", - info.kind.descr())); + expn_data.kind.descr())); err.help(&format!( "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate", suggested_limit)); @@ -504,22 +494,21 @@ impl<'a, 'b> MacroExpander<'a, 'b> { InvocationKind::Bang { mac, .. } => match ext { SyntaxExtensionKind::Bang(expander) => { self.gate_proc_macro_expansion_kind(span, fragment_kind); - let tok_result = expander.expand(self.cx, span, mac.node.stream()); + let tok_result = expander.expand(self.cx, span, mac.stream()); let result = - self.parse_ast_fragment(tok_result, fragment_kind, &mac.node.path, span); + self.parse_ast_fragment(tok_result, fragment_kind, &mac.path, span); self.gate_proc_macro_expansion(span, &result); result } SyntaxExtensionKind::LegacyBang(expander) => { let prev = self.cx.current_expansion.prior_type_ascription; - self.cx.current_expansion.prior_type_ascription = - mac.node.prior_type_ascription; - let tok_result = expander.expand(self.cx, span, mac.node.stream()); + self.cx.current_expansion.prior_type_ascription = mac.prior_type_ascription; + let tok_result = expander.expand(self.cx, span, mac.stream()); let result = if let Some(result) = fragment_kind.make_from(tok_result) { result } else { let msg = format!("non-{kind} macro in {kind} position: {path}", - kind = fragment_kind.name(), path = mac.node.path); + kind = fragment_kind.name(), path = mac.path); self.cx.span_err(span, &msg); self.cx.trace_macros_diag(); fragment_kind.dummy(span) @@ -772,7 +761,7 @@ impl<'a> Parser<'a> { let msg = format!("macro expansion ignores token `{}` and any following", self.this_token_to_string()); // Avoid emitting backtrace info twice. - let def_site_span = self.token.span.with_ctxt(SyntaxContext::empty()); + let def_site_span = self.token.span.with_ctxt(SyntaxContext::root()); let mut err = self.diagnostic().struct_span_err(def_site_span, &msg); err.span_label(span, "caused by the macro expansion here"); let msg = format!( @@ -809,17 +798,20 @@ struct InvocationCollector<'a, 'b> { impl<'a, 'b> InvocationCollector<'a, 'b> { fn collect(&mut self, fragment_kind: AstFragmentKind, kind: InvocationKind) -> AstFragment { - // Expansion info for all the collected invocations is set upon their resolution, + // Expansion data for all the collected invocations is set upon their resolution, // with exception of the derive container case which is not resolved and can get - // its expansion info immediately. - let expn_info = match &kind { - InvocationKind::DeriveContainer { item, .. } => Some(ExpnInfo::default( - ExpnKind::Macro(MacroKind::Attr, sym::derive), - item.span(), self.cx.parse_sess.edition, - )), + // its expansion data immediately. + let expn_data = match &kind { + InvocationKind::DeriveContainer { item, .. } => Some(ExpnData { + parent: self.cx.current_expansion.id, + ..ExpnData::default( + ExpnKind::Macro(MacroKind::Attr, sym::derive), + item.span(), self.cx.parse_sess.edition, + ) + }), _ => None, }; - let expn_id = ExpnId::fresh(self.cx.current_expansion.id, expn_info); + let expn_id = ExpnId::fresh(expn_data); self.invocations.push(Invocation { kind, fragment_kind, @@ -1251,30 +1243,30 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { } let filename = self.cx.resolve_path(&*file.as_str(), it.span()); - match fs::read_to_string(&filename) { - Ok(src) => { - let src_interned = Symbol::intern(&src); - - // Add this input file to the code map to make it available as - // dependency information - self.cx.source_map().new_source_file(filename.into(), src); + match self.cx.source_map().load_file(&filename) { + Ok(source_file) => { + let src = source_file.src.as_ref() + .expect("freshly loaded file should have a source"); + let src_interned = Symbol::intern(src.as_str()); let include_info = vec![ ast::NestedMetaItem::MetaItem( attr::mk_name_value_item_str( - Ident::with_empty_ctxt(sym::file), - dummy_spanned(file), + Ident::with_dummy_span(sym::file), + file, + DUMMY_SP, ), ), ast::NestedMetaItem::MetaItem( attr::mk_name_value_item_str( - Ident::with_empty_ctxt(sym::contents), - dummy_spanned(src_interned), + Ident::with_dummy_span(sym::contents), + src_interned, + DUMMY_SP, ), ), ]; - let include_ident = Ident::with_empty_ctxt(sym::include); + let include_ident = Ident::with_dummy_span(sym::include); let item = attr::mk_list_item(include_ident, include_info); items.push(ast::NestedMetaItem::MetaItem(item)); } @@ -1336,7 +1328,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { } } - let meta = attr::mk_list_item(Ident::with_empty_ctxt(sym::doc), items); + let meta = attr::mk_list_item(Ident::with_dummy_span(sym::doc), items); *at = attr::Attribute { span: at.span, id: at.id, diff --git a/src/libsyntax/ext/placeholders.rs b/src/libsyntax/ext/placeholders.rs index b2b17b0fb28..d800cfedcfb 100644 --- a/src/libsyntax/ext/placeholders.rs +++ b/src/libsyntax/ext/placeholders.rs @@ -2,7 +2,6 @@ use crate::ast::{self, NodeId}; use crate::source_map::{DUMMY_SP, dummy_spanned}; use crate::ext::base::ExtCtxt; use crate::ext::expand::{AstFragment, AstFragmentKind}; -use crate::ext::hygiene::ExpnId; use crate::tokenstream::TokenStream; use crate::mut_visit::*; use crate::ptr::P; @@ -14,12 +13,13 @@ use rustc_data_structures::fx::FxHashMap; pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId) -> AstFragment { fn mac_placeholder() -> ast::Mac { - dummy_spanned(ast::Mac_ { + ast::Mac { path: ast::Path { span: DUMMY_SP, segments: Vec::new() }, tts: TokenStream::empty().into(), delim: ast::MacDelimiter::Brace, + span: DUMMY_SP, prior_type_ascription: None, - }) + } } let ident = ast::Ident::invalid(); @@ -85,11 +85,11 @@ impl<'a, 'b> PlaceholderExpander<'a, 'b> { } } - pub fn add(&mut self, id: ast::NodeId, mut fragment: AstFragment, derives: Vec<ExpnId>) { + pub fn add(&mut self, id: ast::NodeId, mut fragment: AstFragment, placeholders: Vec<NodeId>) { fragment.mut_visit_with(self); if let AstFragment::Items(mut items) = fragment { - for derive in derives { - match self.remove(NodeId::placeholder_from_expn_id(derive)) { + for placeholder in placeholders { + match self.remove(placeholder) { AstFragment::Items(derived_items) => items.extend(derived_items), _ => unreachable!(), } diff --git a/src/libsyntax/ext/proc_macro_server.rs b/src/libsyntax/ext/proc_macro_server.rs index 36621ce7775..1619fa69941 100644 --- a/src/libsyntax/ext/proc_macro_server.rs +++ b/src/libsyntax/ext/proc_macro_server.rs @@ -362,10 +362,10 @@ pub(crate) struct Rustc<'a> { impl<'a> Rustc<'a> { pub fn new(cx: &'a ExtCtxt<'_>) -> Self { // No way to determine def location for a proc macro right now, so use call location. - let location = cx.current_expansion.id.expn_info().unwrap().call_site; + let location = cx.current_expansion.id.expn_data().call_site; let to_span = |transparency| { location.with_ctxt( - SyntaxContext::empty() + SyntaxContext::root() .apply_mark_with_transparency(cx.current_expansion.id, transparency), ) }; @@ -677,7 +677,7 @@ impl server::Span for Rustc<'_> { self.sess.source_map().lookup_char_pos(span.lo()).file } fn parent(&mut self, span: Self::Span) -> Option<Self::Span> { - span.ctxt().outer_expn_info().map(|i| i.call_site) + span.parent() } fn source(&mut self, span: Self::Span) -> Self::Span { span.source_callsite() diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 08a113b53d0..bce0b07db1c 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -30,7 +30,6 @@ use crate::tokenstream::TokenTree; use errors::{Applicability, DiagnosticBuilder, Handler}; use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::sync::Lock; use rustc_target::spec::abi::Abi; use syntax_pos::{Span, DUMMY_SP, MultiSpan}; use log::debug; @@ -462,9 +461,6 @@ declare_features! ( // Allows using `#[doc(keyword = "...")]`. (active, doc_keyword, "1.28.0", Some(51315), None), - // Allows async and await syntax. - (active, async_await, "1.28.0", Some(50547), None), - // Allows reinterpretation of the bits of a value of one type as another type during const eval. (active, const_transmute, "1.29.0", Some(53605), None), @@ -560,6 +556,9 @@ declare_features! ( // Allows `impl Trait` to be used inside type aliases (RFC 2515). (active, type_alias_impl_trait, "1.38.0", Some(63063), None), + // Allows the use of or-patterns, e.g. `0 | 1`. + (active, or_patterns, "1.38.0", Some(54883), None), + // ------------------------------------------------------------------------- // feature-group-end: actual feature gates // ------------------------------------------------------------------------- @@ -572,6 +571,7 @@ pub const INCOMPLETE_FEATURES: &[Symbol] = &[ sym::impl_trait_in_bindings, sym::generic_associated_types, sym::const_generics, + sym::or_patterns, sym::let_chains, ]; @@ -854,6 +854,8 @@ declare_features! ( (accepted, repr_align_enum, "1.37.0", Some(57996), None), // Allows `const _: TYPE = VALUE`. (accepted, underscore_const_names, "1.37.0", Some(54912), None), + // Allows free and inherent `async fn`s, `async` blocks, and `<expr>.await` expressions. + (accepted, async_await, "1.38.0", Some(50547), None), // ------------------------------------------------------------------------- // feature-group-end: accepted features @@ -1956,7 +1958,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { ast::ItemKind::Enum(ast::EnumDef{ref variants, ..}, ..) => { for variant in variants { - match (&variant.node.data, &variant.node.disr_expr) { + match (&variant.data, &variant.disr_expr) { (ast::VariantData::Unit(..), _) => {}, (_, Some(disr_expr)) => gate_feature_post!( @@ -2088,11 +2090,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { "type ascription is experimental"); } } - ast::ExprKind::Yield(..) => { - gate_feature_post!(&self, generators, - e.span, - "yield syntax is experimental"); - } ast::ExprKind::TryBlock(_) => { gate_feature_post!(&self, try_blocks, e.span, "`try` expression is experimental"); } @@ -2102,12 +2099,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { "labels on blocks are unstable"); } } - ast::ExprKind::Async(..) => { - gate_feature_post!(&self, async_await, e.span, "async blocks are unstable"); - } - ast::ExprKind::Await(_) => { - gate_feature_post!(&self, async_await, e.span, "async/await is unstable"); - } _ => {} } visit::walk_expr(self, e) @@ -2156,11 +2147,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { span: Span, _node_id: NodeId) { if let Some(header) = fn_kind.header() { - // Check for const fn and async fn declarations. - if header.asyncness.node.is_async() { - gate_feature_post!(&self, async_await, span, "async fn is unstable"); - } - // Stability of const fn methods are covered in // `visit_trait_item` and `visit_impl_item` below; this is // because default methods don't pass through this point. @@ -2200,9 +2186,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { if block.is_none() { self.check_abi(sig.header.abi, ti.span); } - if sig.header.asyncness.node.is_async() { - gate_feature_post!(&self, async_await, ti.span, "async fn is unstable"); - } if sig.decl.c_variadic { gate_feature_post!(&self, c_variadic, ti.span, "C-variadic functions are unstable"); @@ -2427,10 +2410,6 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], features } -fn for_each_in_lock<T>(vec: &Lock<Vec<T>>, f: impl Fn(&T)) { - vec.borrow().iter().for_each(f); -} - pub fn check_crate(krate: &ast::Crate, sess: &ParseSess, features: &Features, @@ -2443,26 +2422,17 @@ pub fn check_crate(krate: &ast::Crate, plugin_attributes, }; - for_each_in_lock(&sess.param_attr_spans, |span| gate_feature!( - &ctx, - param_attrs, - *span, - "attributes on function parameters are unstable" - )); - - for_each_in_lock(&sess.let_chains_spans, |span| gate_feature!( - &ctx, - let_chains, - *span, - "`let` expressions in this position are experimental" - )); - - for_each_in_lock(&sess.async_closure_spans, |span| gate_feature!( - &ctx, - async_closure, - *span, - "async closures are unstable" - )); + macro_rules! gate_all { + ($spans:ident, $gate:ident, $msg:literal) => { + for span in &*sess.$spans.borrow() { gate_feature!(&ctx, $gate, *span, $msg); } + } + } + + gate_all!(param_attr_spans, param_attrs, "attributes on function parameters are unstable"); + gate_all!(let_chains_spans, let_chains, "`let` expressions in this position are experimental"); + gate_all!(async_closure_spans, async_closure, "async closures are unstable"); + gate_all!(yield_spans, generators, "yield syntax is experimental"); + gate_all!(or_pattern_spans, or_patterns, "or-patterns syntax is experimental"); let visitor = &mut PostExpansionVisitor { context: &ctx, diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index be04c6a76b0..9785f8e2de0 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -383,10 +383,11 @@ pub fn noop_visit_use_tree<T: MutVisitor>(use_tree: &mut UseTree, vis: &mut T) { } pub fn noop_visit_arm<T: MutVisitor>( - Arm { attrs, pats, guard, body, span }: &mut Arm, + Arm { attrs, pats, guard, body, span, id }: &mut Arm, vis: &mut T, ) { visit_attrs(attrs, vis); + vis.visit_id(id); visit_vec(pats, |pat| vis.visit_pat(pat)); visit_opt(guard, |guard| vis.visit_expr(guard)); vis.visit_expr(body); @@ -455,7 +456,7 @@ pub fn noop_visit_foreign_mod<T: MutVisitor>(foreign_mod: &mut ForeignMod, vis: } pub fn noop_visit_variant<T: MutVisitor>(variant: &mut Variant, vis: &mut T) { - let Spanned { node: Variant_ { ident, attrs, id, data, disr_expr }, span } = variant; + let Variant { ident, attrs, id, data, disr_expr, span } = variant; vis.visit_ident(ident); visit_attrs(attrs, vis); vis.visit_id(id); @@ -532,8 +533,8 @@ pub fn noop_visit_attribute<T: MutVisitor>(attr: &mut Attribute, vis: &mut T) { vis.visit_span(span); } -pub fn noop_visit_mac<T: MutVisitor>(Spanned { node, span }: &mut Mac, vis: &mut T) { - let Mac_ { path, delim: _, tts, .. } = node; +pub fn noop_visit_mac<T: MutVisitor>(mac: &mut Mac, vis: &mut T) { + let Mac { path, delim: _, tts, span, prior_type_ascription: _ } = mac; vis.visit_path(path); vis.visit_tts(tts); vis.visit_span(span); @@ -808,9 +809,10 @@ pub fn noop_visit_struct_field<T: MutVisitor>(f: &mut StructField, visitor: &mut } pub fn noop_visit_field<T: MutVisitor>(f: &mut Field, vis: &mut T) { - let Field { ident, expr, span, is_shorthand: _, attrs } = f; + let Field { ident, expr, span, is_shorthand: _, attrs, id } = f; vis.visit_ident(ident); vis.visit_expr(expr); + vis.visit_id(id); vis.visit_span(span); visit_thin_attrs(attrs, vis); } @@ -1040,14 +1042,14 @@ pub fn noop_visit_pat<T: MutVisitor>(pat: &mut P<Pat>, vis: &mut T) { } PatKind::Struct(path, fields, _etc) => { vis.visit_path(path); - for Spanned { node: FieldPat { ident, pat, is_shorthand: _, attrs }, span } in fields { + for FieldPat { ident, pat, is_shorthand: _, attrs, id, span } in fields { vis.visit_ident(ident); + vis.visit_id(id); vis.visit_pat(pat); visit_thin_attrs(attrs, vis); vis.visit_span(span); }; } - PatKind::Tuple(elems) => visit_vec(elems, |elem| vis.visit_pat(elem)), PatKind::Box(inner) => vis.visit_pat(inner), PatKind::Ref(inner, _mutbl) => vis.visit_pat(inner), PatKind::Range(e1, e2, Spanned { span: _, node: _ }) => { @@ -1055,7 +1057,9 @@ pub fn noop_visit_pat<T: MutVisitor>(pat: &mut P<Pat>, vis: &mut T) { vis.visit_expr(e2); vis.visit_span(span); } - PatKind::Slice(elems) => visit_vec(elems, |elem| vis.visit_pat(elem)), + PatKind::Tuple(elems) + | PatKind::Slice(elems) + | PatKind::Or(elems) => visit_vec(elems, |elem| vis.visit_pat(elem)), PatKind::Paren(inner) => vis.visit_pat(inner), PatKind::Mac(mac) => vis.visit_mac(mac), } @@ -1179,7 +1183,7 @@ pub fn noop_visit_expr<T: MutVisitor>(Expr { node, id, span, attrs }: &mut Expr, } ExprKind::InlineAsm(asm) => { let InlineAsm { asm: _, asm_str_style: _, outputs, inputs, clobbers: _, volatile: _, - alignstack: _, dialect: _, ctxt: _ } = asm.deref_mut(); + alignstack: _, dialect: _ } = asm.deref_mut(); for out in outputs { let InlineAsmOutput { constraint: _, expr, is_rw: _, is_indirect: _ } = out; vis.visit_expr(expr); diff --git a/src/libsyntax/parse/diagnostics.rs b/src/libsyntax/parse/diagnostics.rs index 730efb5ef01..1fbf28fb830 100644 --- a/src/libsyntax/parse/diagnostics.rs +++ b/src/libsyntax/parse/diagnostics.rs @@ -8,7 +8,6 @@ use crate::parse::parser::{BlockMode, PathStyle, SemiColonMode, TokenType, Token use crate::parse::token::{self, TokenKind}; use crate::print::pprust; use crate::ptr::P; -use crate::source_map::Spanned; use crate::symbol::{kw, sym}; use crate::ThinVec; use crate::util::parser::AssocOp; @@ -592,18 +591,18 @@ impl<'a> Parser<'a> { crate fn maybe_report_invalid_custom_discriminants( sess: &ParseSess, - variants: &[Spanned<ast::Variant_>], + variants: &[ast::Variant], ) { - let has_fields = variants.iter().any(|variant| match variant.node.data { + let has_fields = variants.iter().any(|variant| match variant.data { VariantData::Tuple(..) | VariantData::Struct(..) => true, VariantData::Unit(..) => false, }); - let discriminant_spans = variants.iter().filter(|variant| match variant.node.data { + let discriminant_spans = variants.iter().filter(|variant| match variant.data { VariantData::Tuple(..) | VariantData::Struct(..) => false, VariantData::Unit(..) => true, }) - .filter_map(|variant| variant.node.disr_expr.as_ref().map(|c| c.value.span)) + .filter_map(|variant| variant.disr_expr.as_ref().map(|c| c.value.span)) .collect::<Vec<_>>(); if !discriminant_spans.is_empty() && has_fields { @@ -618,7 +617,7 @@ impl<'a> Parser<'a> { err.span_label(sp, "disallowed custom discriminant"); } for variant in variants.iter() { - match &variant.node.data { + match &variant.data { VariantData::Struct(..) => { err.span_label( variant.span, diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index e86d4c7fde6..66add869359 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -4,13 +4,11 @@ use crate::symbol::{sym, Symbol}; use crate::parse::unescape_error_reporting::{emit_unescape_error, push_escaped_char}; use errors::{FatalError, DiagnosticBuilder}; -use syntax_pos::{BytePos, Pos, Span, NO_EXPANSION}; +use syntax_pos::{BytePos, Pos, Span}; use rustc_lexer::Base; use rustc_lexer::unescape; -use std::borrow::Cow; use std::char; -use std::iter; use std::convert::TryInto; use rustc_data_structures::sync::Lrc; use log::debug; @@ -84,7 +82,7 @@ impl<'a> StringReader<'a> { fn mk_sp(&self, lo: BytePos, hi: BytePos) -> Span { - self.override_span.unwrap_or_else(|| Span::new(lo, hi, NO_EXPANSION)) + self.override_span.unwrap_or_else(|| Span::with_root_ctxt(lo, hi)) } /// Returns the next token, including trivia like whitespace or comments. @@ -181,18 +179,7 @@ impl<'a> StringReader<'a> { let string = self.str_from(start); // comments with only more "/"s are not doc comments let tok = if is_doc_comment(string) { - let mut idx = 0; - loop { - idx = match string[idx..].find('\r') { - None => break, - Some(it) => idx + it + 1 - }; - if string[idx..].chars().next() != Some('\n') { - self.err_span_(start + BytePos(idx as u32 - 1), - start + BytePos(idx as u32), - "bare CR not allowed in doc-comment"); - } - } + self.forbid_bare_cr(start, string, "bare CR not allowed in doc-comment"); token::DocComment(Symbol::intern(string)) } else { token::Comment @@ -217,15 +204,10 @@ impl<'a> StringReader<'a> { } let tok = if is_doc_comment { - let has_cr = string.contains('\r'); - let string = if has_cr { - self.translate_crlf(start, - string, - "bare CR not allowed in block doc-comment") - } else { - string.into() - }; - token::DocComment(Symbol::intern(&string[..])) + self.forbid_bare_cr(start, + string, + "bare CR not allowed in block doc-comment"); + token::DocComment(Symbol::intern(string)) } else { token::Comment }; @@ -291,9 +273,6 @@ impl<'a> StringReader<'a> { } rustc_lexer::TokenKind::Semi => token::Semi, rustc_lexer::TokenKind::Comma => token::Comma, - rustc_lexer::TokenKind::DotDotDot => token::DotDotDot, - rustc_lexer::TokenKind::DotDotEq => token::DotDotEq, - rustc_lexer::TokenKind::DotDot => token::DotDot, rustc_lexer::TokenKind::Dot => token::Dot, rustc_lexer::TokenKind::OpenParen => token::OpenDelim(token::Paren), rustc_lexer::TokenKind::CloseParen => token::CloseDelim(token::Paren), @@ -305,42 +284,20 @@ impl<'a> StringReader<'a> { rustc_lexer::TokenKind::Pound => token::Pound, rustc_lexer::TokenKind::Tilde => token::Tilde, rustc_lexer::TokenKind::Question => token::Question, - rustc_lexer::TokenKind::ColonColon => token::ModSep, rustc_lexer::TokenKind::Colon => token::Colon, rustc_lexer::TokenKind::Dollar => token::Dollar, - rustc_lexer::TokenKind::EqEq => token::EqEq, rustc_lexer::TokenKind::Eq => token::Eq, - rustc_lexer::TokenKind::FatArrow => token::FatArrow, - rustc_lexer::TokenKind::Ne => token::Ne, rustc_lexer::TokenKind::Not => token::Not, - rustc_lexer::TokenKind::Le => token::Le, - rustc_lexer::TokenKind::LArrow => token::LArrow, rustc_lexer::TokenKind::Lt => token::Lt, - rustc_lexer::TokenKind::ShlEq => token::BinOpEq(token::Shl), - rustc_lexer::TokenKind::Shl => token::BinOp(token::Shl), - rustc_lexer::TokenKind::Ge => token::Ge, rustc_lexer::TokenKind::Gt => token::Gt, - rustc_lexer::TokenKind::ShrEq => token::BinOpEq(token::Shr), - rustc_lexer::TokenKind::Shr => token::BinOp(token::Shr), - rustc_lexer::TokenKind::RArrow => token::RArrow, rustc_lexer::TokenKind::Minus => token::BinOp(token::Minus), - rustc_lexer::TokenKind::MinusEq => token::BinOpEq(token::Minus), rustc_lexer::TokenKind::And => token::BinOp(token::And), - rustc_lexer::TokenKind::AndEq => token::BinOpEq(token::And), - rustc_lexer::TokenKind::AndAnd => token::AndAnd, rustc_lexer::TokenKind::Or => token::BinOp(token::Or), - rustc_lexer::TokenKind::OrEq => token::BinOpEq(token::Or), - rustc_lexer::TokenKind::OrOr => token::OrOr, rustc_lexer::TokenKind::Plus => token::BinOp(token::Plus), - rustc_lexer::TokenKind::PlusEq => token::BinOpEq(token::Plus), rustc_lexer::TokenKind::Star => token::BinOp(token::Star), - rustc_lexer::TokenKind::StarEq => token::BinOpEq(token::Star), rustc_lexer::TokenKind::Slash => token::BinOp(token::Slash), - rustc_lexer::TokenKind::SlashEq => token::BinOpEq(token::Slash), rustc_lexer::TokenKind::Caret => token::BinOp(token::Caret), - rustc_lexer::TokenKind::CaretEq => token::BinOpEq(token::Caret), rustc_lexer::TokenKind::Percent => token::BinOp(token::Percent), - rustc_lexer::TokenKind::PercentEq => token::BinOpEq(token::Percent), rustc_lexer::TokenKind::Unknown => { let c = self.str_from(start).chars().next().unwrap(); @@ -516,49 +473,16 @@ impl<'a> StringReader<'a> { &self.src[self.src_index(start)..self.src_index(end)] } - /// Converts CRLF to LF in the given string, raising an error on bare CR. - fn translate_crlf<'b>(&self, start: BytePos, s: &'b str, errmsg: &'b str) -> Cow<'b, str> { - let mut chars = s.char_indices().peekable(); - while let Some((i, ch)) = chars.next() { - if ch == '\r' { - if let Some((lf_idx, '\n')) = chars.peek() { - return translate_crlf_(self, start, s, *lf_idx, chars, errmsg).into(); - } - let pos = start + BytePos(i as u32); - let end_pos = start + BytePos((i + ch.len_utf8()) as u32); - self.err_span_(pos, end_pos, errmsg); - } - } - return s.into(); - - fn translate_crlf_(rdr: &StringReader<'_>, - start: BytePos, - s: &str, - mut j: usize, - mut chars: iter::Peekable<impl Iterator<Item = (usize, char)>>, - errmsg: &str) - -> String { - let mut buf = String::with_capacity(s.len()); - // Skip first CR - buf.push_str(&s[.. j - 1]); - while let Some((i, ch)) = chars.next() { - if ch == '\r' { - if j < i { - buf.push_str(&s[j..i]); - } - let next = i + ch.len_utf8(); - j = next; - if chars.peek().map(|(_, ch)| *ch) != Some('\n') { - let pos = start + BytePos(i as u32); - let end_pos = start + BytePos(next as u32); - rdr.err_span_(pos, end_pos, errmsg); - } - } - } - if j < s.len() { - buf.push_str(&s[j..]); - } - buf + fn forbid_bare_cr(&self, start: BytePos, s: &str, errmsg: &str) { + let mut idx = 0; + loop { + idx = match s[idx..].find('\r') { + None => break, + Some(it) => idx + it + 1 + }; + self.err_span_(start + BytePos(idx as u32 - 1), + start + BytePos(idx as u32), + errmsg); } } diff --git a/src/libsyntax/parse/lexer/tests.rs b/src/libsyntax/parse/lexer/tests.rs index fc47e4f0b18..a915aa42fd1 100644 --- a/src/libsyntax/parse/lexer/tests.rs +++ b/src/libsyntax/parse/lexer/tests.rs @@ -1,41 +1,17 @@ use super::*; -use crate::ast::CrateConfig; use crate::symbol::Symbol; use crate::source_map::{SourceMap, FilePathMapping}; -use crate::feature_gate::UnstableFeatures; use crate::parse::token; -use crate::diagnostics::plugin::ErrorMap; use crate::with_default_globals; use std::io; use std::path::PathBuf; -use syntax_pos::{BytePos, Span, NO_EXPANSION, edition::Edition}; -use rustc_data_structures::fx::{FxHashSet, FxHashMap}; -use rustc_data_structures::sync::{Lock, Once}; +use errors::{Handler, emitter::EmitterWriter}; +use syntax_pos::{BytePos, Span}; fn mk_sess(sm: Lrc<SourceMap>) -> ParseSess { - let emitter = errors::emitter::EmitterWriter::new(Box::new(io::sink()), - Some(sm.clone()), - false, - false, - false); - ParseSess { - span_diagnostic: errors::Handler::with_emitter(true, None, Box::new(emitter)), - unstable_features: UnstableFeatures::from_environment(), - config: CrateConfig::default(), - included_mod_stack: Lock::new(Vec::new()), - source_map: sm, - missing_fragment_specifiers: Lock::new(FxHashSet::default()), - raw_identifier_spans: Lock::new(Vec::new()), - registered_diagnostics: Lock::new(ErrorMap::new()), - buffered_lints: Lock::new(vec![]), - edition: Edition::from_session(), - ambiguous_block_expr_parse: Lock::new(FxHashMap::default()), - param_attr_spans: Lock::new(Vec::new()), - let_chains_spans: Lock::new(Vec::new()), - async_closure_spans: Lock::new(Vec::new()), - injected_crate_name: Once::new(), - } + let emitter = EmitterWriter::new(Box::new(io::sink()), Some(sm.clone()), false, false, false); + ParseSess::with_span_handler(Handler::with_emitter(true, None, Box::new(emitter)), sm) } // open a string reader for the given string @@ -61,7 +37,7 @@ fn t1() { let tok1 = string_reader.next_token(); let tok2 = Token::new( mk_ident("fn"), - Span::new(BytePos(21), BytePos(23), NO_EXPANSION), + Span::with_root_ctxt(BytePos(21), BytePos(23)), ); assert_eq!(tok1.kind, tok2.kind); assert_eq!(tok1.span, tok2.span); @@ -71,7 +47,7 @@ fn t1() { assert_eq!(string_reader.pos.clone(), BytePos(28)); let tok4 = Token::new( mk_ident("main"), - Span::new(BytePos(24), BytePos(28), NO_EXPANSION), + Span::with_root_ctxt(BytePos(24), BytePos(28)), ); assert_eq!(tok3.kind, tok4.kind); assert_eq!(tok3.span, tok4.span); @@ -99,42 +75,50 @@ fn mk_lit(kind: token::LitKind, symbol: &str, suffix: Option<&str>) -> TokenKind } #[test] -fn doublecolonparsing() { +fn doublecolon_parsing() { with_default_globals(|| { let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let sh = mk_sess(sm.clone()); - check_tokenization(setup(&sm, &sh, "a b".to_string()), - vec![mk_ident("a"), token::Whitespace, mk_ident("b")]); + check_tokenization( + setup(&sm, &sh, "a b".to_string()), + vec![mk_ident("a"), token::Whitespace, mk_ident("b")], + ); }) } #[test] -fn dcparsing_2() { +fn doublecolon_parsing_2() { with_default_globals(|| { let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let sh = mk_sess(sm.clone()); - check_tokenization(setup(&sm, &sh, "a::b".to_string()), - vec![mk_ident("a"), token::ModSep, mk_ident("b")]); + check_tokenization( + setup(&sm, &sh, "a::b".to_string()), + vec![mk_ident("a"), token::Colon, token::Colon, mk_ident("b")], + ); }) } #[test] -fn dcparsing_3() { +fn doublecolon_parsing_3() { with_default_globals(|| { let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let sh = mk_sess(sm.clone()); - check_tokenization(setup(&sm, &sh, "a ::b".to_string()), - vec![mk_ident("a"), token::Whitespace, token::ModSep, mk_ident("b")]); + check_tokenization( + setup(&sm, &sh, "a ::b".to_string()), + vec![mk_ident("a"), token::Whitespace, token::Colon, token::Colon, mk_ident("b")], + ); }) } #[test] -fn dcparsing_4() { +fn doublecolon_parsing_4() { with_default_globals(|| { let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let sh = mk_sess(sm.clone()); - check_tokenization(setup(&sm, &sh, "a:: b".to_string()), - vec![mk_ident("a"), token::ModSep, token::Whitespace, mk_ident("b")]); + check_tokenization( + setup(&sm, &sh, "a:: b".to_string()), + vec![mk_ident("a"), token::Colon, token::Colon, token::Whitespace, mk_ident("b")], + ); }) } diff --git a/src/libsyntax/parse/lexer/tokentrees.rs b/src/libsyntax/parse/lexer/tokentrees.rs index 37e67a2729e..e5ba7e45309 100644 --- a/src/libsyntax/parse/lexer/tokentrees.rs +++ b/src/libsyntax/parse/lexer/tokentrees.rs @@ -39,29 +39,29 @@ struct TokenTreesReader<'a> { impl<'a> TokenTreesReader<'a> { // Parse a stream of tokens into a list of `TokenTree`s, up to an `Eof`. fn parse_all_token_trees(&mut self) -> PResult<'a, TokenStream> { - let mut tts = Vec::new(); + let mut buf = TokenStreamBuilder::default(); self.real_token(); while self.token != token::Eof { - tts.push(self.parse_token_tree()?); + buf.push(self.parse_token_tree()?); } - Ok(TokenStream::new(tts)) + Ok(buf.into_token_stream()) } // Parse a stream of tokens into a list of `TokenTree`s, up to a `CloseDelim`. fn parse_token_trees_until_close_delim(&mut self) -> TokenStream { - let mut tts = vec![]; + let mut buf = TokenStreamBuilder::default(); loop { if let token::CloseDelim(..) = self.token.kind { - return TokenStream::new(tts); + return buf.into_token_stream(); } match self.parse_token_tree() { - Ok(tree) => tts.push(tree), + Ok(tree) => buf.push(tree), Err(mut e) => { e.emit(); - return TokenStream::new(tts); + return buf.into_token_stream(); } } } @@ -223,8 +223,32 @@ impl<'a> TokenTreesReader<'a> { _ => { self.token = token; return; - }, + } + } + } + } +} + +#[derive(Default)] +struct TokenStreamBuilder { + buf: Vec<TreeAndJoint>, +} + +impl TokenStreamBuilder { + fn push(&mut self, (tree, joint): TreeAndJoint) { + if let Some((TokenTree::Token(prev_token), Joint)) = self.buf.last() { + if let TokenTree::Token(token) = &tree { + if let Some(glued) = prev_token.glue(token) { + self.buf.pop(); + self.buf.push((TokenTree::Token(glued), joint)); + return; + } } } + self.buf.push((tree, joint)) + } + + fn into_token_stream(self) -> TokenStream { + TokenStream::new(self.buf) } } diff --git a/src/libsyntax/parse/lexer/unicode_chars.rs b/src/libsyntax/parse/lexer/unicode_chars.rs index eaa736c6a35..525b4215aff 100644 --- a/src/libsyntax/parse/lexer/unicode_chars.rs +++ b/src/libsyntax/parse/lexer/unicode_chars.rs @@ -3,7 +3,7 @@ use super::StringReader; use errors::{Applicability, DiagnosticBuilder}; -use syntax_pos::{BytePos, Pos, Span, NO_EXPANSION, symbol::kw}; +use syntax_pos::{BytePos, Pos, Span, symbol::kw}; use crate::parse::token; #[rustfmt::skip] // for line breaks @@ -343,7 +343,7 @@ crate fn check_for_substitution<'a>( None => return None, }; - let span = Span::new(pos, pos + Pos::from_usize(ch.len_utf8()), NO_EXPANSION); + let span = Span::with_root_ctxt(pos, pos + Pos::from_usize(ch.len_utf8())); let (ascii_name, token) = match ASCII_ARRAY.iter().find(|&&(c, _, _)| c == ascii_char) { Some((_ascii_char, ascii_name, token)) => (ascii_name, token), @@ -362,10 +362,9 @@ crate fn check_for_substitution<'a>( ascii_char, ascii_name ); err.span_suggestion( - Span::new( + Span::with_root_ctxt( pos, pos + Pos::from_usize('“'.len_utf8() + s.len() + '”'.len_utf8()), - NO_EXPANSION, ), &msg, format!("\"{}\"", s), diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 80aa7a35266..b1f3612a839 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -16,6 +16,7 @@ use errors::{Applicability, FatalError, Level, Handler, ColorConfig, Diagnostic, use rustc_data_structures::sync::{Lrc, Lock, Once}; use syntax_pos::{Span, SourceFile, FileName, MultiSpan}; use syntax_pos::edition::Edition; +use syntax_pos::hygiene::ExpnId; use rustc_data_structures::fx::{FxHashSet, FxHashMap}; use std::borrow::Cow; @@ -62,7 +63,11 @@ pub struct ParseSess { pub let_chains_spans: Lock<Vec<Span>>, // Places where `async || ..` exprs were used and should be feature gated. pub async_closure_spans: Lock<Vec<Span>>, + // Places where `yield e?` exprs were used and should be feature gated. + pub yield_spans: Lock<Vec<Span>>, pub injected_crate_name: Once<Symbol>, + // Places where or-patterns e.g. `Some(Foo | Bar)` were used and should be feature gated. + pub or_pattern_spans: Lock<Vec<Span>>, } impl ParseSess { @@ -86,12 +91,14 @@ impl ParseSess { included_mod_stack: Lock::new(vec![]), source_map, buffered_lints: Lock::new(vec![]), - edition: Edition::from_session(), + edition: ExpnId::root().expn_data().edition, ambiguous_block_expr_parse: Lock::new(FxHashMap::default()), param_attr_spans: Lock::new(Vec::new()), let_chains_spans: Lock::new(Vec::new()), async_closure_spans: Lock::new(Vec::new()), + yield_spans: Lock::new(Vec::new()), injected_crate_name: Once::new(), + or_pattern_spans: Lock::new(Vec::new()), } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 1c1428c5713..89725d8b339 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -13,7 +13,6 @@ mod generics; use crate::ast::{self, AttrStyle, Attribute, Arg, BindingMode, StrStyle, SelfKind}; use crate::ast::{FnDecl, Ident, IsAsync, MacDelimiter, Mutability, TyKind}; use crate::ast::{Visibility, VisibilityKind, Unsafety, CrateSugar}; -use crate::ext::hygiene::SyntaxContext; use crate::source_map::{self, respan}; use crate::parse::{SeqSep, literal, token}; use crate::parse::lexer::UnmatchedBrace; @@ -1101,7 +1100,7 @@ impl<'a> Parser<'a> { crate fn process_potential_macro_variable(&mut self) { self.token = match self.token.kind { - token::Dollar if self.token.span.ctxt() != SyntaxContext::empty() && + token::Dollar if self.token.span.from_expansion() && self.look_ahead(1, |t| t.is_ident()) => { self.bump(); let name = match self.token.kind { @@ -1236,7 +1235,7 @@ impl<'a> Parser<'a> { let args: Vec<_> = args.into_iter().filter_map(|x| x).collect(); - if c_variadic && args.is_empty() { + if c_variadic && args.len() <= 1 { self.span_err(sp, "C-variadic function must be declared with at least one named argument"); } diff --git a/src/libsyntax/parse/parser/expr.rs b/src/libsyntax/parse/parser/expr.rs index 4432c1329cb..ccc6bd15067 100644 --- a/src/libsyntax/parse/parser/expr.rs +++ b/src/libsyntax/parse/parser/expr.rs @@ -8,13 +8,13 @@ use crate::ast::{self, Attribute, AttrStyle, Ident, CaptureBy, BlockCheckMode}; use crate::ast::{Expr, ExprKind, RangeLimits, Label, Movability, IsAsync, Arm}; use crate::ast::{Ty, TyKind, FunctionRetTy, Arg, FnDecl}; use crate::ast::{BinOpKind, BinOp, UnOp}; -use crate::ast::{Mac_, AnonConst, Field}; +use crate::ast::{Mac, AnonConst, Field}; use crate::parse::classify; use crate::parse::token::{self, Token}; use crate::parse::diagnostics::{Error}; use crate::print::pprust; -use crate::source_map::{self, respan, Span}; +use crate::source_map::{self, Span}; use crate::symbol::{kw, sym}; use crate::util::parser::{AssocOp, Fixity, prec_let_scrutinee_needs_par}; @@ -224,6 +224,10 @@ impl<'a> Parser<'a> { self.err_dotdotdot_syntax(self.token.span); } + if self.token == token::LArrow { + self.err_larrow_operator(self.token.span); + } + self.bump(); if op.is_comparison() { self.check_no_chained_comparison(&lhs, &op); @@ -993,6 +997,9 @@ impl<'a> Parser<'a> { } else { ex = ExprKind::Yield(None); } + + let span = lo.to(hi); + self.sess.yield_spans.borrow_mut().push(span); } else if self.eat_keyword(kw::Let) { return self.parse_let_expr(attrs); } else if is_span_rust_2018 && self.eat_keyword(kw::Await) { @@ -1007,12 +1014,13 @@ impl<'a> Parser<'a> { // MACRO INVOCATION expression let (delim, tts) = self.expect_delimited_token_tree()?; hi = self.prev_span; - ex = ExprKind::Mac(respan(lo.to(hi), Mac_ { + ex = ExprKind::Mac(Mac { path, tts, delim, + span: lo.to(hi), prior_type_ascription: self.last_type_ascription, - })); + }); } else if self.check(&token::OpenDelim(token::Brace)) { if let Some(expr) = self.maybe_parse_struct_expr(lo, &path, &attrs) { return expr; @@ -1199,7 +1207,7 @@ impl<'a> Parser<'a> { if self.eat_keyword(kw::Else) || !cond.returns() { let sp = self.sess.source_map().next_point(lo); let mut err = self.diagnostic() - .struct_span_err(sp, "missing condition for `if` statemement"); + .struct_span_err(sp, "missing condition for `if` expression"); err.span_label(sp, "expected if condition here"); return Err(err) } @@ -1444,6 +1452,7 @@ impl<'a> Parser<'a> { guard, body: expr, span: lo.to(hi), + id: ast::DUMMY_NODE_ID, }) } @@ -1599,6 +1608,7 @@ impl<'a> Parser<'a> { expr: self.mk_expr(self.token.span, ExprKind::Err, ThinVec::new()), is_shorthand: false, attrs: ThinVec::new(), + id: ast::DUMMY_NODE_ID, }); } } @@ -1684,6 +1694,7 @@ impl<'a> Parser<'a> { expr, is_shorthand, attrs: attrs.into(), + id: ast::DUMMY_NODE_ID, }) } @@ -1702,6 +1713,19 @@ impl<'a> Parser<'a> { .emit(); } + fn err_larrow_operator(&self, span: Span) { + self.struct_span_err( + span, + "unexpected token: `<-`" + ).span_suggestion( + span, + "if you meant to write a comparison against a negative value, add a \ + space in between `<` and `-`", + "< -".to_string(), + Applicability::MaybeIncorrect + ).emit(); + } + fn mk_assign_op(&self, binop: BinOp, lhs: P<Expr>, rhs: P<Expr>) -> ExprKind { ExprKind::AssignOp(binop, lhs, rhs) } diff --git a/src/libsyntax/parse/parser/item.rs b/src/libsyntax/parse/parser/item.rs index e85ef9cc974..72819c99660 100644 --- a/src/libsyntax/parse/parser/item.rs +++ b/src/libsyntax/parse/parser/item.rs @@ -10,7 +10,7 @@ use crate::ast::{Visibility, VisibilityKind, Mutability, FnDecl, FnHeader}; use crate::ast::{ForeignItem, ForeignItemKind}; use crate::ast::{Ty, TyKind, GenericBounds, TraitRef}; use crate::ast::{EnumDef, VariantData, StructField, AnonConst}; -use crate::ast::{Mac, Mac_, MacDelimiter}; +use crate::ast::{Mac, MacDelimiter}; use crate::ext::base::DummyResult; use crate::parse::token; use crate::parse::parser::maybe_append; @@ -530,12 +530,13 @@ impl<'a> Parser<'a> { } let hi = self.prev_span; - let mac = respan(mac_lo.to(hi), Mac_ { + let mac = Mac { path, tts, delim, + span: mac_lo.to(hi), prior_type_ascription: self.last_type_ascription, - }); + }; let item = self.mk_item(lo.to(hi), Ident::invalid(), ItemKind::Mac(mac), visibility, attrs); return Ok(Some(item)); @@ -604,12 +605,13 @@ impl<'a> Parser<'a> { self.expect(&token::Semi)?; } - Ok(Some(respan(lo.to(self.prev_span), Mac_ { + Ok(Some(Mac { path, tts, delim, + span: lo.to(self.prev_span), prior_type_ascription: self.last_type_ascription, - }))) + })) } else { Ok(None) } @@ -1564,14 +1566,15 @@ impl<'a> Parser<'a> { None }; - let vr = ast::Variant_ { + let vr = ast::Variant { ident, id: ast::DUMMY_NODE_ID, attrs: variant_attrs, data: struct_def, disr_expr, + span: vlo.to(self.prev_span), }; - variants.push(respan(vlo.to(self.prev_span), vr)); + variants.push(vr); if !self.eat(&token::Comma) { if self.token.is_ident() && !self.token.is_reserved_ident() { diff --git a/src/libsyntax/parse/parser/module.rs b/src/libsyntax/parse/parser/module.rs index 58a7ffba948..3f6f87b1c44 100644 --- a/src/libsyntax/parse/parser/module.rs +++ b/src/libsyntax/parse/parser/module.rs @@ -60,7 +60,7 @@ impl<'a> Parser<'a> { // Record that we fetched the mod from an external file if warn { let attr = attr::mk_attr_outer( - attr::mk_word_item(Ident::with_empty_ctxt(sym::warn_directory_ownership))); + attr::mk_word_item(Ident::with_dummy_span(sym::warn_directory_ownership))); attr::mark_known(&attr); attrs.push(attr); } diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index 5cc428a4df1..fd458aec743 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -2,8 +2,8 @@ use super::{Parser, PResult, PathStyle}; use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole}; use crate::ptr::P; -use crate::ast::{self, Attribute, Pat, PatKind, FieldPat, RangeEnd, RangeSyntax, Mac_}; -use crate::ast::{BindingMode, Ident, Mutability, Expr, ExprKind}; +use crate::ast::{self, Attribute, Pat, PatKind, FieldPat, RangeEnd, RangeSyntax, Mac}; +use crate::ast::{BindingMode, Ident, Mutability, Path, QSelf, Expr, ExprKind}; use crate::parse::token::{self}; use crate::print::pprust; use crate::source_map::{respan, Span, Spanned}; @@ -14,7 +14,10 @@ use errors::{Applicability, DiagnosticBuilder}; impl<'a> Parser<'a> { /// Parses a pattern. - pub fn parse_pat(&mut self, expected: Option<&'static str>) -> PResult<'a, P<Pat>> { + pub fn parse_pat( + &mut self, + expected: Option<&'static str> + ) -> PResult<'a, P<Pat>> { self.parse_pat_with_range_pat(true, expected) } @@ -97,6 +100,34 @@ impl<'a> Parser<'a> { Ok(()) } + /// Parses a pattern, that may be a or-pattern (e.g. `Some(Foo | Bar)`). + fn parse_pat_with_or(&mut self, expected: Option<&'static str>) -> PResult<'a, P<Pat>> { + // Parse the first pattern. + let first_pat = self.parse_pat(expected)?; + + // If the next token is not a `|`, this is not an or-pattern and + // we should exit here. + if !self.check(&token::BinOp(token::Or)) { + return Ok(first_pat) + } + + let lo = first_pat.span; + + let mut pats = vec![first_pat]; + + while self.eat(&token::BinOp(token::Or)) { + pats.push(self.parse_pat_with_range_pat( + true, expected + )?); + } + + let or_pattern_span = lo.to(self.prev_span); + + self.sess.or_pattern_spans.borrow_mut().push(or_pattern_span); + + Ok(self.mk_pat(or_pattern_span, PatKind::Or(pats))) + } + /// Parses a pattern, with a setting whether modern range patterns (e.g., `a..=b`, `a..b` are /// allowed). fn parse_pat_with_range_pat( @@ -108,93 +139,52 @@ impl<'a> Parser<'a> { maybe_whole!(self, NtPat, |x| x); let lo = self.token.span; - let pat; - match self.token.kind { - token::BinOp(token::And) | token::AndAnd => { - // Parse &pat / &mut pat - self.expect_and()?; - let mutbl = self.parse_mutability(); - if let token::Lifetime(name) = self.token.kind { - let mut err = self.fatal(&format!("unexpected lifetime `{}` in pattern", name)); - err.span_label(self.token.span, "unexpected lifetime"); - return Err(err); - } - let subpat = self.parse_pat_with_range_pat(false, expected)?; - pat = PatKind::Ref(subpat, mutbl); - } - token::OpenDelim(token::Paren) => { - // Parse a tuple or parenthesis pattern. - let (fields, trailing_comma) = self.parse_paren_comma_seq(|p| p.parse_pat(None))?; - - // Here, `(pat,)` is a tuple pattern. - // For backward compatibility, `(..)` is a tuple pattern as well. - pat = if fields.len() == 1 && !(trailing_comma || fields[0].is_rest()) { - PatKind::Paren(fields.into_iter().nth(0).unwrap()) - } else { - PatKind::Tuple(fields) - }; - } + let pat = match self.token.kind { + token::BinOp(token::And) | token::AndAnd => self.parse_pat_deref(expected)?, + token::OpenDelim(token::Paren) => self.parse_pat_tuple_or_parens()?, token::OpenDelim(token::Bracket) => { // Parse `[pat, pat,...]` as a slice pattern. - let (slice, _) = self.parse_delim_comma_seq(token::Bracket, |p| p.parse_pat(None))?; - pat = PatKind::Slice(slice); + PatKind::Slice(self.parse_delim_comma_seq(token::Bracket, |p| p.parse_pat(None))?.0) } token::DotDot => { self.bump(); - pat = if self.is_pat_range_end_start() { + if self.is_pat_range_end_start() { // Parse `..42` for recovery. self.parse_pat_range_to(RangeEnd::Excluded, "..")? } else { // A rest pattern `..`. PatKind::Rest - }; + } } token::DotDotEq => { // Parse `..=42` for recovery. self.bump(); - pat = self.parse_pat_range_to(RangeEnd::Included(RangeSyntax::DotDotEq), "..=")?; + self.parse_pat_range_to(RangeEnd::Included(RangeSyntax::DotDotEq), "..=")? } token::DotDotDot => { // Parse `...42` for recovery. self.bump(); - pat = self.parse_pat_range_to(RangeEnd::Included(RangeSyntax::DotDotDot), "...")?; + self.parse_pat_range_to(RangeEnd::Included(RangeSyntax::DotDotDot), "...")? } // At this point, token != &, &&, (, [ _ => if self.eat_keyword(kw::Underscore) { // Parse _ - pat = PatKind::Wild; + PatKind::Wild } else if self.eat_keyword(kw::Mut) { - // Parse mut ident @ pat / mut ref ident @ pat - let mutref_span = self.prev_span.to(self.token.span); - let binding_mode = if self.eat_keyword(kw::Ref) { - self.diagnostic() - .struct_span_err(mutref_span, "the order of `mut` and `ref` is incorrect") - .span_suggestion( - mutref_span, - "try switching the order", - "ref mut".into(), - Applicability::MachineApplicable - ).emit(); - BindingMode::ByRef(Mutability::Mutable) - } else { - BindingMode::ByValue(Mutability::Mutable) - }; - pat = self.parse_pat_ident(binding_mode)?; + self.recover_pat_ident_mut_first()? } else if self.eat_keyword(kw::Ref) { // Parse ref ident @ pat / ref mut ident @ pat let mutbl = self.parse_mutability(); - pat = self.parse_pat_ident(BindingMode::ByRef(mutbl))?; + self.parse_pat_ident(BindingMode::ByRef(mutbl))? } else if self.eat_keyword(kw::Box) { - // Parse box pat - let subpat = self.parse_pat_with_range_pat(false, None)?; - pat = PatKind::Box(subpat); + // Parse `box pat` + PatKind::Box(self.parse_pat_with_range_pat(false, None)?) } else if self.token.is_ident() && !self.token.is_reserved_ident() && self.parse_as_ident() { - // Parse ident @ pat + // Parse `ident @ pat` // This can give false positives and parse nullary enums, - // they are dealt with later in resolve - let binding_mode = BindingMode::ByValue(Mutability::Immutable); - pat = self.parse_pat_ident(binding_mode)?; + // they are dealt with later in resolve. + self.parse_pat_ident(BindingMode::ByValue(Mutability::Immutable))? } else if self.token.is_path_start() { // Parse pattern starting with a path let (qself, path) = if self.eat_lt() { @@ -206,136 +196,189 @@ impl<'a> Parser<'a> { (None, self.parse_path(PathStyle::Expr)?) }; match self.token.kind { - token::Not if qself.is_none() => { - // Parse macro invocation - self.bump(); - let (delim, tts) = self.expect_delimited_token_tree()?; - let mac = respan(lo.to(self.prev_span), Mac_ { - path, - tts, - delim, - prior_type_ascription: self.last_type_ascription, - }); - pat = PatKind::Mac(mac); - } + token::Not if qself.is_none() => self.parse_pat_mac_invoc(lo, path)?, token::DotDotDot | token::DotDotEq | token::DotDot => { - let (end_kind, form) = match self.token.kind { - token::DotDot => (RangeEnd::Excluded, ".."), - token::DotDotDot => (RangeEnd::Included(RangeSyntax::DotDotDot), "..."), - token::DotDotEq => (RangeEnd::Included(RangeSyntax::DotDotEq), "..="), - _ => panic!("can only parse `..`/`...`/`..=` for ranges \ - (checked above)"), - }; - let op_span = self.token.span; - // Parse range - let span = lo.to(self.prev_span); - let begin = self.mk_expr(span, ExprKind::Path(qself, path), ThinVec::new()); - self.bump(); - let end = self.parse_pat_range_end_opt(&begin, form)?; - pat = PatKind::Range(begin, end, respan(op_span, end_kind)); + self.parse_pat_range_starting_with_path(lo, qself, path)? } - token::OpenDelim(token::Brace) => { - if qself.is_some() { - let msg = "unexpected `{` after qualified path"; - let mut err = self.fatal(msg); - err.span_label(self.token.span, msg); - return Err(err); - } - // Parse struct pattern - self.bump(); - let (fields, etc) = self.parse_pat_fields().unwrap_or_else(|mut e| { - e.emit(); - self.recover_stmt(); - (vec![], true) - }); - self.bump(); - pat = PatKind::Struct(path, fields, etc); - } - token::OpenDelim(token::Paren) => { - if qself.is_some() { - let msg = "unexpected `(` after qualified path"; - let mut err = self.fatal(msg); - err.span_label(self.token.span, msg); - return Err(err); - } - // Parse tuple struct or enum pattern - let (fields, _) = self.parse_paren_comma_seq(|p| p.parse_pat(None))?; - pat = PatKind::TupleStruct(path, fields) - } - _ => pat = PatKind::Path(qself, path), + token::OpenDelim(token::Brace) => self.parse_pat_struct(qself, path)?, + token::OpenDelim(token::Paren) => self.parse_pat_tuple_struct(qself, path)?, + _ => PatKind::Path(qself, path), } } else { // Try to parse everything else as literal with optional minus match self.parse_literal_maybe_minus() { - Ok(begin) => { - let op_span = self.token.span; - if self.check(&token::DotDot) || self.check(&token::DotDotEq) || - self.check(&token::DotDotDot) { - let (end_kind, form) = if self.eat(&token::DotDotDot) { - (RangeEnd::Included(RangeSyntax::DotDotDot), "...") - } else if self.eat(&token::DotDotEq) { - (RangeEnd::Included(RangeSyntax::DotDotEq), "..=") - } else if self.eat(&token::DotDot) { - (RangeEnd::Excluded, "..") - } else { - panic!("impossible case: we already matched \ - on a range-operator token") - }; - let end = self.parse_pat_range_end_opt(&begin, form)?; - pat = PatKind::Range(begin, end, respan(op_span, end_kind)) - } else { - pat = PatKind::Lit(begin); - } - } - Err(mut err) => { - self.cancel(&mut err); - let expected = expected.unwrap_or("pattern"); - let msg = format!( - "expected {}, found {}", - expected, - self.this_token_descr(), - ); - let mut err = self.fatal(&msg); - err.span_label(self.token.span, format!("expected {}", expected)); - let sp = self.sess.source_map().start_point(self.token.span); - if let Some(sp) = self.sess.ambiguous_block_expr_parse.borrow().get(&sp) { - self.sess.expr_parentheses_needed(&mut err, *sp, None); - } - return Err(err); + Ok(begin) + if self.check(&token::DotDot) + || self.check(&token::DotDotEq) + || self.check(&token::DotDotDot) => + { + self.parse_pat_range_starting_with_lit(begin)? } + Ok(begin) => PatKind::Lit(begin), + Err(err) => return self.fatal_unexpected_non_pat(err, expected), } } - } + }; let pat = self.mk_pat(lo.to(self.prev_span), pat); let pat = self.maybe_recover_from_bad_qpath(pat, true)?; if !allow_range_pat { - match pat.node { - PatKind::Range( - _, _, Spanned { node: RangeEnd::Included(RangeSyntax::DotDotDot), .. } - ) => {}, - PatKind::Range(..) => { - let mut err = self.struct_span_err( - pat.span, - "the range pattern here has ambiguous interpretation", - ); - err.span_suggestion( - pat.span, - "add parentheses to clarify the precedence", - format!("({})", pprust::pat_to_string(&pat)), - // "ambiguous interpretation" implies that we have to be guessing - Applicability::MaybeIncorrect - ); - return Err(err); - } - _ => {} - } + self.ban_pat_range_if_ambiguous(&pat)? } Ok(pat) } + /// Ban a range pattern if it has an ambiguous interpretation. + fn ban_pat_range_if_ambiguous(&self, pat: &Pat) -> PResult<'a, ()> { + match pat.node { + PatKind::Range( + .., Spanned { node: RangeEnd::Included(RangeSyntax::DotDotDot), .. } + ) => return Ok(()), + PatKind::Range(..) => {} + _ => return Ok(()), + } + + let mut err = self.struct_span_err( + pat.span, + "the range pattern here has ambiguous interpretation", + ); + err.span_suggestion( + pat.span, + "add parentheses to clarify the precedence", + format!("({})", pprust::pat_to_string(&pat)), + // "ambiguous interpretation" implies that we have to be guessing + Applicability::MaybeIncorrect + ); + Err(err) + } + + /// Parse `&pat` / `&mut pat`. + fn parse_pat_deref(&mut self, expected: Option<&'static str>) -> PResult<'a, PatKind> { + self.expect_and()?; + let mutbl = self.parse_mutability(); + + if let token::Lifetime(name) = self.token.kind { + let mut err = self.fatal(&format!("unexpected lifetime `{}` in pattern", name)); + err.span_label(self.token.span, "unexpected lifetime"); + return Err(err); + } + + let subpat = self.parse_pat_with_range_pat(false, expected)?; + Ok(PatKind::Ref(subpat, mutbl)) + } + + /// Parse a tuple or parenthesis pattern. + fn parse_pat_tuple_or_parens(&mut self) -> PResult<'a, PatKind> { + let (fields, trailing_comma) = self.parse_paren_comma_seq(|p| { + p.parse_pat_with_or(None) + })?; + + // Here, `(pat,)` is a tuple pattern. + // For backward compatibility, `(..)` is a tuple pattern as well. + Ok(if fields.len() == 1 && !(trailing_comma || fields[0].is_rest()) { + PatKind::Paren(fields.into_iter().nth(0).unwrap()) + } else { + PatKind::Tuple(fields) + }) + } + + /// Recover on `mut ref? ident @ pat` and suggest + /// that the order of `mut` and `ref` is incorrect. + fn recover_pat_ident_mut_first(&mut self) -> PResult<'a, PatKind> { + let mutref_span = self.prev_span.to(self.token.span); + let binding_mode = if self.eat_keyword(kw::Ref) { + self.struct_span_err(mutref_span, "the order of `mut` and `ref` is incorrect") + .span_suggestion( + mutref_span, + "try switching the order", + "ref mut".into(), + Applicability::MachineApplicable + ) + .emit(); + BindingMode::ByRef(Mutability::Mutable) + } else { + BindingMode::ByValue(Mutability::Mutable) + }; + self.parse_pat_ident(binding_mode) + } + + /// Parse macro invocation + fn parse_pat_mac_invoc(&mut self, lo: Span, path: Path) -> PResult<'a, PatKind> { + self.bump(); + let (delim, tts) = self.expect_delimited_token_tree()?; + let mac = Mac { + path, + tts, + delim, + span: lo.to(self.prev_span), + prior_type_ascription: self.last_type_ascription, + }; + Ok(PatKind::Mac(mac)) + } + + /// Parse a range pattern `$path $form $end?` where `$form = ".." | "..." | "..=" ;`. + /// The `$path` has already been parsed and the next token is the `$form`. + fn parse_pat_range_starting_with_path( + &mut self, + lo: Span, + qself: Option<QSelf>, + path: Path + ) -> PResult<'a, PatKind> { + let (end_kind, form) = match self.token.kind { + token::DotDot => (RangeEnd::Excluded, ".."), + token::DotDotDot => (RangeEnd::Included(RangeSyntax::DotDotDot), "..."), + token::DotDotEq => (RangeEnd::Included(RangeSyntax::DotDotEq), "..="), + _ => panic!("can only parse `..`/`...`/`..=` for ranges (checked above)"), + }; + let op_span = self.token.span; + // Parse range + let span = lo.to(self.prev_span); + let begin = self.mk_expr(span, ExprKind::Path(qself, path), ThinVec::new()); + self.bump(); + let end = self.parse_pat_range_end_opt(&begin, form)?; + Ok(PatKind::Range(begin, end, respan(op_span, end_kind))) + } + + /// Parse a range pattern `$literal $form $end?` where `$form = ".." | "..." | "..=" ;`. + /// The `$path` has already been parsed and the next token is the `$form`. + fn parse_pat_range_starting_with_lit(&mut self, begin: P<Expr>) -> PResult<'a, PatKind> { + let op_span = self.token.span; + let (end_kind, form) = if self.eat(&token::DotDotDot) { + (RangeEnd::Included(RangeSyntax::DotDotDot), "...") + } else if self.eat(&token::DotDotEq) { + (RangeEnd::Included(RangeSyntax::DotDotEq), "..=") + } else if self.eat(&token::DotDot) { + (RangeEnd::Excluded, "..") + } else { + panic!("impossible case: we already matched on a range-operator token") + }; + let end = self.parse_pat_range_end_opt(&begin, form)?; + Ok(PatKind::Range(begin, end, respan(op_span, end_kind))) + } + + fn fatal_unexpected_non_pat( + &mut self, + mut err: DiagnosticBuilder<'a>, + expected: Option<&'static str>, + ) -> PResult<'a, P<Pat>> { + self.cancel(&mut err); + + let expected = expected.unwrap_or("pattern"); + let msg = format!("expected {}, found {}", expected, self.this_token_descr()); + + let mut err = self.fatal(&msg); + err.span_label(self.token.span, format!("expected {}", expected)); + + let sp = self.sess.source_map().start_point(self.token.span); + if let Some(sp) = self.sess.ambiguous_block_expr_parse.borrow().get(&sp) { + self.sess.expr_parentheses_needed(&mut err, *sp, None); + } + + Err(err) + } + // Helper function to decide whether to parse as ident binding // or to try to do something more complex like range patterns. fn parse_as_ident(&mut self) -> bool { @@ -421,11 +464,9 @@ impl<'a> Parser<'a> { } /// Parses `ident` or `ident @ pat`. - /// used by the copy foo and ref foo patterns to give a good + /// Used by the copy foo and ref foo patterns to give a good /// error message when parsing mistakes like `ref foo(a, b)`. - fn parse_pat_ident(&mut self, - binding_mode: ast::BindingMode) - -> PResult<'a, PatKind> { + fn parse_pat_ident(&mut self, binding_mode: BindingMode) -> PResult<'a, PatKind> { let ident = self.parse_ident()?; let sub = if self.eat(&token::At) { Some(self.parse_pat(Some("binding pattern"))?) @@ -433,23 +474,54 @@ impl<'a> Parser<'a> { None }; - // just to be friendly, if they write something like - // ref Some(i) - // we end up here with ( as the current token. This shortly - // leads to a parse error. Note that if there is no explicit + // Just to be friendly, if they write something like `ref Some(i)`, + // we end up here with `(` as the current token. + // This shortly leads to a parse error. Note that if there is no explicit // binding mode then we do not end up here, because the lookahead - // will direct us over to parse_enum_variant() + // will direct us over to `parse_enum_variant()`. if self.token == token::OpenDelim(token::Paren) { return Err(self.span_fatal( self.prev_span, - "expected identifier, found enum pattern")) + "expected identifier, found enum pattern", + )) } Ok(PatKind::Ident(binding_mode, ident, sub)) } + /// Parse a struct ("record") pattern (e.g. `Foo { ... }` or `Foo::Bar { ... }`). + fn parse_pat_struct(&mut self, qself: Option<QSelf>, path: Path) -> PResult<'a, PatKind> { + if qself.is_some() { + let msg = "unexpected `{` after qualified path"; + let mut err = self.fatal(msg); + err.span_label(self.token.span, msg); + return Err(err); + } + + self.bump(); + let (fields, etc) = self.parse_pat_fields().unwrap_or_else(|mut e| { + e.emit(); + self.recover_stmt(); + (vec![], true) + }); + self.bump(); + Ok(PatKind::Struct(path, fields, etc)) + } + + /// Parse tuple struct or tuple variant pattern (e.g. `Foo(...)` or `Foo::Bar(...)`). + fn parse_pat_tuple_struct(&mut self, qself: Option<QSelf>, path: Path) -> PResult<'a, PatKind> { + if qself.is_some() { + let msg = "unexpected `(` after qualified path"; + let mut err = self.fatal(msg); + err.span_label(self.token.span, msg); + return Err(err); + } + let (fields, _) = self.parse_paren_comma_seq(|p| p.parse_pat_with_or(None))?; + Ok(PatKind::TupleStruct(path, fields)) + } + /// Parses the fields of a struct-like pattern. - fn parse_pat_fields(&mut self) -> PResult<'a, (Vec<Spanned<FieldPat>>, bool)> { + fn parse_pat_fields(&mut self) -> PResult<'a, (Vec<FieldPat>, bool)> { let mut fields = Vec::new(); let mut etc = false; let mut ate_comma = true; @@ -482,17 +554,7 @@ impl<'a> Parser<'a> { etc = true; let mut etc_sp = self.token.span; - if self.token == token::DotDotDot { // Issue #46718 - // Accept `...` as if it were `..` to avoid further errors - self.struct_span_err(self.token.span, "expected field pattern, found `...`") - .span_suggestion( - self.token.span, - "to omit remaining fields, use one fewer `.`", - "..".to_owned(), - Applicability::MachineApplicable - ) - .emit(); - } + self.recover_one_fewer_dotdot(); self.bump(); // `..` || `...` if self.token == token::CloseDelim(token::Brace) { @@ -574,18 +636,31 @@ impl<'a> Parser<'a> { return Ok((fields, etc)); } - fn parse_pat_field( - &mut self, - lo: Span, - attrs: Vec<Attribute> - ) -> PResult<'a, Spanned<FieldPat>> { + /// Recover on `...` as if it were `..` to avoid further errors. + /// See issue #46718. + fn recover_one_fewer_dotdot(&self) { + if self.token != token::DotDotDot { + return; + } + + self.struct_span_err(self.token.span, "expected field pattern, found `...`") + .span_suggestion( + self.token.span, + "to omit remaining fields, use one fewer `.`", + "..".to_owned(), + Applicability::MachineApplicable + ) + .emit(); + } + + fn parse_pat_field(&mut self, lo: Span, attrs: Vec<Attribute>) -> PResult<'a, FieldPat> { // Check if a colon exists one ahead. This means we're parsing a fieldname. let hi; let (subpat, fieldname, is_shorthand) = if self.look_ahead(1, |t| t == &token::Colon) { // Parsing a pattern of the form "fieldname: pat" let fieldname = self.parse_field_name()?; self.bump(); - let pat = self.parse_pat(None)?; + let pat = self.parse_pat_with_or(None)?; hi = pat.span; (pat, fieldname, false) } else { @@ -613,14 +688,13 @@ impl<'a> Parser<'a> { (subpat, fieldname, true) }; - Ok(Spanned { + Ok(FieldPat { + ident: fieldname, + pat: subpat, + is_shorthand, + attrs: attrs.into(), + id: ast::DUMMY_NODE_ID, span: lo.to(hi), - node: FieldPat { - ident: fieldname, - pat: subpat, - is_shorthand, - attrs: attrs.into(), - } }) } diff --git a/src/libsyntax/parse/parser/stmt.rs b/src/libsyntax/parse/parser/stmt.rs index f182edcbff4..c911caba4cd 100644 --- a/src/libsyntax/parse/parser/stmt.rs +++ b/src/libsyntax/parse/parser/stmt.rs @@ -5,7 +5,7 @@ use super::path::PathStyle; use crate::ptr::P; use crate::{maybe_whole, ThinVec}; use crate::ast::{self, Stmt, StmtKind, Local, Block, BlockCheckMode, Expr, ExprKind}; -use crate::ast::{Attribute, AttrStyle, VisibilityKind, MacStmtStyle, Mac_, MacDelimiter}; +use crate::ast::{Attribute, AttrStyle, VisibilityKind, MacStmtStyle, Mac, MacDelimiter}; use crate::ext::base::DummyResult; use crate::parse::{classify, DirectoryOwnership}; use crate::parse::diagnostics::Error; @@ -99,12 +99,13 @@ impl<'a> Parser<'a> { MacStmtStyle::NoBraces }; - let mac = respan(lo.to(hi), Mac_ { + let mac = Mac { path, tts, delim, + span: lo.to(hi), prior_type_ascription: self.last_type_ascription, - }); + }; let node = if delim == MacDelimiter::Brace || self.token == token::Semi || self.token == token::Eof { StmtKind::Mac(P((mac, style, attrs.into()))) @@ -167,7 +168,22 @@ impl<'a> Parser<'a> { if self.token == token::Semi { unused_attrs(&attrs, self); self.bump(); - return Ok(None); + let mut last_semi = lo; + while self.token == token::Semi { + last_semi = self.token.span; + self.bump(); + } + // We are encoding a string of semicolons as an + // an empty tuple that spans the excess semicolons + // to preserve this info until the lint stage + return Ok(Some(Stmt { + id: ast::DUMMY_NODE_ID, + span: lo.to(last_semi), + node: StmtKind::Semi(self.mk_expr(lo.to(last_semi), + ExprKind::Tup(Vec::new()), + ThinVec::new() + )), + })); } if self.token == token::CloseDelim(token::Brace) { diff --git a/src/libsyntax/parse/parser/ty.rs b/src/libsyntax/parse/parser/ty.rs index 1eb3d441e69..337702b8d30 100644 --- a/src/libsyntax/parse/parser/ty.rs +++ b/src/libsyntax/parse/parser/ty.rs @@ -4,9 +4,9 @@ use crate::{maybe_whole, maybe_recover_from_interpolated_ty_qpath}; use crate::ptr::P; use crate::ast::{self, Ty, TyKind, MutTy, BareFnTy, FunctionRetTy, GenericParam, Lifetime, Ident}; use crate::ast::{TraitBoundModifier, TraitObjectSyntax, GenericBound, GenericBounds, PolyTraitRef}; -use crate::ast::{Mutability, AnonConst, FnDecl, Mac_}; +use crate::ast::{Mutability, AnonConst, FnDecl, Mac}; use crate::parse::token::{self, Token}; -use crate::source_map::{respan, Span}; +use crate::source_map::Span; use crate::symbol::{kw}; use rustc_target::spec::abi::Abi; @@ -175,13 +175,14 @@ impl<'a> Parser<'a> { if self.eat(&token::Not) { // Macro invocation in type position let (delim, tts) = self.expect_delimited_token_tree()?; - let node = Mac_ { + let mac = Mac { path, tts, delim, + span: lo.to(self.prev_span), prior_type_ascription: self.last_type_ascription, }; - TyKind::Mac(respan(lo.to(self.prev_span), node)) + TyKind::Mac(mac) } else { // Just a type path or bound list (trait object type) starting with a trait. // `Type` diff --git a/src/libsyntax/parse/tests.rs b/src/libsyntax/parse/tests.rs index e619fd17fb5..6a789ef99d6 100644 --- a/src/libsyntax/parse/tests.rs +++ b/src/libsyntax/parse/tests.rs @@ -12,7 +12,7 @@ use crate::symbol::{kw, sym}; use crate::tests::{matches_codepattern, string_to_stream, with_error_checking_parse}; use crate::tokenstream::{DelimSpan, TokenTree, TokenStream}; use crate::with_default_globals; -use syntax_pos::{Span, BytePos, Pos, NO_EXPANSION}; +use syntax_pos::{Span, BytePos, Pos}; use std::path::PathBuf; @@ -27,7 +27,7 @@ fn parse_item_from_source_str(name: FileName, source: String, sess: &ParseSess) // produce a syntax_pos::span fn sp(a: u32, b: u32) -> Span { - Span::new(BytePos(a), BytePos(b), NO_EXPANSION) + Span::with_root_ctxt(BytePos(a), BytePos(b)) } /// Parse a string, return an expr @@ -172,8 +172,8 @@ fn get_spans_of_pat_idents(src: &str) -> Vec<Span> { impl<'a> crate::visit::Visitor<'a> for PatIdentVisitor { fn visit_pat(&mut self, p: &'a ast::Pat) { match p.node { - PatKind::Ident(_ , ref spannedident, _) => { - self.spans.push(spannedident.span.clone()); + PatKind::Ident(_ , ref ident, _) => { + self.spans.push(ident.span.clone()); } _ => { crate::visit::walk_pat(self, p); @@ -273,7 +273,7 @@ fn ttdelim_span() { "foo!( fn main() { body } )".to_string(), &sess).unwrap(); let tts: Vec<_> = match expr.node { - ast::ExprKind::Mac(ref mac) => mac.node.stream().trees().collect(), + ast::ExprKind::Mac(ref mac) => mac.stream().trees().collect(), _ => panic!("not a macro"), }; diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index be800b4de66..1865f925165 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -551,7 +551,7 @@ impl Token { } } - crate fn glue(self, joint: Token) -> Option<Token> { + crate fn glue(&self, joint: &Token) -> Option<Token> { let kind = match self.kind { Eq => match joint.kind { Eq => EqEq, diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index bda761244d5..4dc00af4860 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -123,13 +123,13 @@ pub fn print_crate<'a>(cm: &'a SourceMap, // of the feature gate, so we fake them up here. // #![feature(prelude_import)] - let pi_nested = attr::mk_nested_word_item(ast::Ident::with_empty_ctxt(sym::prelude_import)); - let list = attr::mk_list_item(ast::Ident::with_empty_ctxt(sym::feature), vec![pi_nested]); + let pi_nested = attr::mk_nested_word_item(ast::Ident::with_dummy_span(sym::prelude_import)); + let list = attr::mk_list_item(ast::Ident::with_dummy_span(sym::feature), vec![pi_nested]); let fake_attr = attr::mk_attr_inner(list); s.print_attribute(&fake_attr); // #![no_std] - let no_std_meta = attr::mk_word_item(ast::Ident::with_empty_ctxt(sym::no_std)); + let no_std_meta = attr::mk_word_item(ast::Ident::with_dummy_span(sym::no_std)); let fake_attr = attr::mk_attr_inner(no_std_meta); s.print_attribute(&fake_attr); } @@ -436,18 +436,30 @@ pub trait PrintState<'a>: std::ops::Deref<Target=pp::Printer> + std::ops::DerefM fn print_ident(&mut self, ident: ast::Ident); fn print_generic_args(&mut self, args: &ast::GenericArgs, colons_before_params: bool); - fn commasep<T, F>(&mut self, b: Breaks, elts: &[T], mut op: F) + fn strsep<T, F>(&mut self, sep: &'static str, space_before: bool, + b: Breaks, elts: &[T], mut op: F) where F: FnMut(&mut Self, &T), { self.rbox(0, b); - let mut first = true; - for elt in elts { - if first { first = false; } else { self.word_space(","); } - op(self, elt); + if let Some((first, rest)) = elts.split_first() { + op(self, first); + for elt in rest { + if space_before { + self.space(); + } + self.word_space(sep); + op(self, elt); + } } self.end(); } + fn commasep<T, F>(&mut self, b: Breaks, elts: &[T], op: F) + where F: FnMut(&mut Self, &T), + { + self.strsep(",", false, b, elts, op) + } + fn maybe_print_comment(&mut self, pos: BytePos) { while let Some(ref cmnt) = self.next_comment() { if cmnt.pos < pos { @@ -1067,7 +1079,7 @@ impl<'a> State<'a> { } ast::ForeignItemKind::Macro(ref m) => { self.print_mac(m); - match m.node.delim { + match m.delim { MacDelimiter::Brace => {}, _ => self.s.word(";") } @@ -1341,7 +1353,7 @@ impl<'a> State<'a> { } ast::ItemKind::Mac(ref mac) => { self.print_mac(mac); - match mac.node.delim { + match mac.delim { MacDelimiter::Brace => {} _ => self.s.word(";"), } @@ -1402,7 +1414,7 @@ impl<'a> State<'a> { for v in variants { self.space_if_not_bol(); self.maybe_print_comment(v.span.lo()); - self.print_outer_attributes(&v.node.attrs); + self.print_outer_attributes(&v.attrs); self.ibox(INDENT_UNIT); self.print_variant(v); self.s.word(","); @@ -1492,8 +1504,8 @@ impl<'a> State<'a> { crate fn print_variant(&mut self, v: &ast::Variant) { self.head(""); let generics = ast::Generics::default(); - self.print_struct(&v.node.data, &generics, v.node.ident, v.span, false); - match v.node.disr_expr { + self.print_struct(&v.data, &generics, v.ident, v.span, false); + match v.disr_expr { Some(ref d) => { self.s.space(); self.word_space("="); @@ -1554,7 +1566,7 @@ impl<'a> State<'a> { } ast::TraitItemKind::Macro(ref mac) => { self.print_mac(mac); - match mac.node.delim { + match mac.delim { MacDelimiter::Brace => {} _ => self.s.word(";"), } @@ -1591,7 +1603,7 @@ impl<'a> State<'a> { } ast::ImplItemKind::Macro(ref mac) => { self.print_mac(mac); - match mac.node.delim { + match mac.delim { MacDelimiter::Brace => {} _ => self.s.word(";"), } @@ -1749,11 +1761,11 @@ impl<'a> State<'a> { crate fn print_mac(&mut self, m: &ast::Mac) { self.print_mac_common( - Some(MacHeader::Path(&m.node.path)), + Some(MacHeader::Path(&m.path)), true, None, - m.node.delim.to_token(), - m.node.stream(), + m.delim.to_token(), + m.stream(), true, m.span, ); @@ -2353,6 +2365,9 @@ impl<'a> State<'a> { self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(p)); self.pclose(); } + PatKind::Or(ref pats) => { + self.strsep("|", true, Inconsistent, &pats[..], |s, p| s.print_pat(p)); + } PatKind::Path(None, ref path) => { self.print_path(path, true, 0); } @@ -2367,14 +2382,14 @@ impl<'a> State<'a> { Consistent, &fields[..], |s, f| { s.cbox(INDENT_UNIT); - if !f.node.is_shorthand { - s.print_ident(f.node.ident); + if !f.is_shorthand { + s.print_ident(f.ident); s.word_nbsp(":"); } - s.print_pat(&f.node.pat); + s.print_pat(&f.pat); s.end(); }, - |f| f.node.pat.span); + |f| f.pat.span); if etc { if !fields.is_empty() { self.word_space(","); } self.s.word(".."); @@ -2429,16 +2444,7 @@ impl<'a> State<'a> { } fn print_pats(&mut self, pats: &[P<ast::Pat>]) { - let mut first = true; - for p in pats { - if first { - first = false; - } else { - self.s.space(); - self.word_space("|"); - } - self.print_pat(p); - } + self.strsep("|", true, Inconsistent, pats, |s, p| s.print_pat(p)); } fn print_arm(&mut self, arm: &ast::Arm) { diff --git a/src/libsyntax/print/pprust/tests.rs b/src/libsyntax/print/pprust/tests.rs index 082a430e0ed..25214673e69 100644 --- a/src/libsyntax/print/pprust/tests.rs +++ b/src/libsyntax/print/pprust/tests.rs @@ -54,14 +54,15 @@ fn test_variant_to_string() { with_default_globals(|| { let ident = ast::Ident::from_str("principal_skinner"); - let var = source_map::respan(syntax_pos::DUMMY_SP, ast::Variant_ { + let var = ast::Variant { ident, attrs: Vec::new(), id: ast::DUMMY_NODE_ID, // making this up as I go.... ? data: ast::VariantData::Unit(ast::DUMMY_NODE_ID), disr_expr: None, - }); + span: syntax_pos::DUMMY_SP, + }; let varstr = variant_to_string(&var); assert_eq!(varstr, "principal_skinner"); diff --git a/src/libsyntax/source_map.rs b/src/libsyntax/source_map.rs index 4e29c77c89e..7190cfd72a9 100644 --- a/src/libsyntax/source_map.rs +++ b/src/libsyntax/source_map.rs @@ -8,7 +8,7 @@ //! information, source code snippets, etc. pub use syntax_pos::*; -pub use syntax_pos::hygiene::{ExpnKind, ExpnInfo}; +pub use syntax_pos::hygiene::{ExpnKind, ExpnData}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::StableHasher; @@ -29,14 +29,15 @@ mod tests; /// Returns the span itself if it doesn't come from a macro expansion, /// otherwise return the call site span up to the `enclosing_sp` by -/// following the `expn_info` chain. +/// following the `expn_data` chain. pub fn original_sp(sp: Span, enclosing_sp: Span) -> Span { - let call_site1 = sp.ctxt().outer_expn_info().map(|ei| ei.call_site); - let call_site2 = enclosing_sp.ctxt().outer_expn_info().map(|ei| ei.call_site); - match (call_site1, call_site2) { - (None, _) => sp, - (Some(call_site1), Some(call_site2)) if call_site1 == call_site2 => sp, - (Some(call_site1), _) => original_sp(call_site1, enclosing_sp), + let expn_data1 = sp.ctxt().outer_expn_data(); + let expn_data2 = enclosing_sp.ctxt().outer_expn_data(); + if expn_data1.is_root() || + !expn_data2.is_root() && expn_data1.call_site == expn_data2.call_site { + sp + } else { + original_sp(expn_data1.call_site, enclosing_sp) } } @@ -170,6 +171,26 @@ impl SourceMap { Ok(self.new_source_file(filename, src)) } + /// Loads source file as a binary blob. + /// + /// Unlike `load_file`, guarantees that no normalization like BOM-removal + /// takes place. + pub fn load_binary_file(&self, path: &Path) -> io::Result<Vec<u8>> { + // Ideally, this should use `self.file_loader`, but it can't + // deal with binary files yet. + let bytes = fs::read(path)?; + + // We need to add file to the `SourceMap`, so that it is present + // in dep-info. There's also an edge case that file might be both + // loaded as a binary via `include_bytes!` and as proper `SourceFile` + // via `mod`, so we try to use real file contents and not just an + // empty string. + let text = std::str::from_utf8(&bytes).unwrap_or("") + .to_string(); + self.new_source_file(path.to_owned().into(), text); + Ok(bytes) + } + pub fn files(&self) -> MappedLockGuard<'_, Vec<Lrc<SourceFile>>> { LockGuard::map(self.files.borrow(), |files| &mut files.source_files) } @@ -519,7 +540,7 @@ impl SourceMap { /// extract function takes three arguments: a string slice containing the source, an index in /// the slice for the beginning of the span and an index in the slice for the end of the span. fn span_to_source<F>(&self, sp: Span, extract_source: F) -> Result<String, SpanSnippetError> - where F: Fn(&str, usize, usize) -> String + where F: Fn(&str, usize, usize) -> Result<String, SpanSnippetError> { if sp.lo() > sp.hi() { return Err(SpanSnippetError::IllFormedSpan(sp)); @@ -554,9 +575,9 @@ impl SourceMap { } if let Some(ref src) = local_begin.sf.src { - return Ok(extract_source(src, start_index, end_index)); + return extract_source(src, start_index, end_index); } else if let Some(src) = local_begin.sf.external_src.borrow().get_source() { - return Ok(extract_source(src, start_index, end_index)); + return extract_source(src, start_index, end_index); } else { return Err(SpanSnippetError::SourceNotAvailable { filename: local_begin.sf.name.clone() @@ -567,8 +588,9 @@ impl SourceMap { /// Returns the source snippet as `String` corresponding to the given `Span` pub fn span_to_snippet(&self, sp: Span) -> Result<String, SpanSnippetError> { - self.span_to_source(sp, |src, start_index, end_index| src[start_index..end_index] - .to_string()) + self.span_to_source(sp, |src, start_index, end_index| src.get(start_index..end_index) + .map(|s| s.to_string()) + .ok_or_else(|| SpanSnippetError::IllFormedSpan(sp))) } pub fn span_to_margin(&self, sp: Span) -> Option<usize> { @@ -582,7 +604,9 @@ impl SourceMap { /// Returns the source snippet as `String` before the given `Span` pub fn span_to_prev_source(&self, sp: Span) -> Result<String, SpanSnippetError> { - self.span_to_source(sp, |src, start_index, _| src[..start_index].to_string()) + self.span_to_source(sp, |src, start_index, _| src.get(..start_index) + .map(|s| s.to_string()) + .ok_or_else(|| SpanSnippetError::IllFormedSpan(sp))) } /// Extend the given `Span` to just after the previous occurrence of `c`. Return the same span diff --git a/src/libsyntax/source_map/tests.rs b/src/libsyntax/source_map/tests.rs index 427e86b56e1..c7b8332c53e 100644 --- a/src/libsyntax/source_map/tests.rs +++ b/src/libsyntax/source_map/tests.rs @@ -91,7 +91,7 @@ fn t6() { fn t7() { // Test span_to_lines for a span ending at the end of source_file let sm = init_source_map(); - let span = Span::new(BytePos(12), BytePos(23), NO_EXPANSION); + let span = Span::with_root_ctxt(BytePos(12), BytePos(23)); let file_lines = sm.span_to_lines(span).unwrap(); assert_eq!(file_lines.file.name, PathBuf::from("blork.rs").into()); @@ -107,7 +107,7 @@ fn span_from_selection(input: &str, selection: &str) -> Span { assert_eq!(input.len(), selection.len()); let left_index = selection.find('~').unwrap() as u32; let right_index = selection.rfind('~').map(|x|x as u32).unwrap_or(left_index); - Span::new(BytePos(left_index), BytePos(right_index + 1), NO_EXPANSION) + Span::with_root_ctxt(BytePos(left_index), BytePos(right_index + 1)) } /// Tests span_to_snippet and span_to_lines for a span converting 3 @@ -137,7 +137,7 @@ fn span_to_snippet_and_lines_spanning_multiple_lines() { fn t8() { // Test span_to_snippet for a span ending at the end of source_file let sm = init_source_map(); - let span = Span::new(BytePos(12), BytePos(23), NO_EXPANSION); + let span = Span::with_root_ctxt(BytePos(12), BytePos(23)); let snippet = sm.span_to_snippet(span); assert_eq!(snippet, Ok("second line".to_string())); @@ -147,7 +147,7 @@ fn t8() { fn t9() { // Test span_to_str for a span ending at the end of source_file let sm = init_source_map(); - let span = Span::new(BytePos(12), BytePos(23), NO_EXPANSION); + let span = Span::with_root_ctxt(BytePos(12), BytePos(23)); let sstr = sm.span_to_string(span); assert_eq!(sstr, "blork.rs:2:1: 2:12"); @@ -198,10 +198,9 @@ impl SourceMapExtension for SourceMap { let lo = hi + offset; hi = lo + substring.len(); if i == n { - let span = Span::new( + let span = Span::with_root_ctxt( BytePos(lo as u32 + file.start_pos.0), BytePos(hi as u32 + file.start_pos.0), - NO_EXPANSION, ); assert_eq!(&self.span_to_snippet(span).unwrap()[..], substring); diff --git a/src/libsyntax/tests.rs b/src/libsyntax/tests.rs index cff034fdeb1..4c0e1e3704d 100644 --- a/src/libsyntax/tests.rs +++ b/src/libsyntax/tests.rs @@ -9,7 +9,7 @@ use crate::with_default_globals; use errors::emitter::EmitterWriter; use errors::Handler; use rustc_data_structures::sync::Lrc; -use syntax_pos::{BytePos, NO_EXPANSION, Span, MultiSpan}; +use syntax_pos::{BytePos, Span, MultiSpan}; use std::io; use std::io::prelude::*; @@ -169,7 +169,7 @@ fn make_span(file_text: &str, start: &Position, end: &Position) -> Span { let start = make_pos(file_text, start); let end = make_pos(file_text, end) + end.string.len(); // just after matching thing ends assert!(start <= end); - Span::new(BytePos(start as u32), BytePos(end as u32), NO_EXPANSION) + Span::with_root_ctxt(BytePos(start as u32), BytePos(end as u32)) } fn make_pos(file_text: &str, pos: &Position) -> usize { diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs index 6ff8898fe21..09a1b93c7bb 100644 --- a/src/libsyntax/tokenstream.rs +++ b/src/libsyntax/tokenstream.rs @@ -414,7 +414,7 @@ impl TokenStreamBuilder { let last_tree_if_joint = self.0.last().and_then(TokenStream::last_tree_if_joint); if let Some(TokenTree::Token(last_token)) = last_tree_if_joint { if let Some((TokenTree::Token(token), is_joint)) = stream.first_tree_and_joint() { - if let Some(glued_tok) = last_token.glue(token) { + if let Some(glued_tok) = last_token.glue(&token) { let last_stream = self.0.pop().unwrap(); self.push_all_but_last_tree(&last_stream); let glued_tt = TokenTree::Token(glued_tok); diff --git a/src/libsyntax/tokenstream/tests.rs b/src/libsyntax/tokenstream/tests.rs index 72e22a49876..5017e5f5424 100644 --- a/src/libsyntax/tokenstream/tests.rs +++ b/src/libsyntax/tokenstream/tests.rs @@ -3,14 +3,14 @@ use super::*; use crate::ast::Name; use crate::with_default_globals; use crate::tests::string_to_stream; -use syntax_pos::{Span, BytePos, NO_EXPANSION}; +use syntax_pos::{Span, BytePos}; fn string_to_ts(string: &str) -> TokenStream { string_to_stream(string.to_owned()) } fn sp(a: u32, b: u32) -> Span { - Span::new(BytePos(a), BytePos(b), NO_EXPANSION) + Span::with_root_ctxt(BytePos(a), BytePos(b)) } #[test] diff --git a/src/libsyntax/util/parser.rs b/src/libsyntax/util/parser.rs index d71358f45c4..a501541c959 100644 --- a/src/libsyntax/util/parser.rs +++ b/src/libsyntax/util/parser.rs @@ -97,6 +97,8 @@ impl AssocOp { // DotDotDot is no longer supported, but we need some way to display the error token::DotDotDot => Some(DotDotEq), token::Colon => Some(Colon), + // `<-` should probably be `< -` + token::LArrow => Some(Less), _ if t.is_keyword(kw::As) => Some(As), _ => None } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 596c5b46b98..91b92d84a81 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -311,11 +311,11 @@ pub fn walk_variant<'a, V>(visitor: &mut V, item_id: NodeId) where V: Visitor<'a>, { - visitor.visit_ident(variant.node.ident); - visitor.visit_variant_data(&variant.node.data, variant.node.ident, + visitor.visit_ident(variant.ident); + visitor.visit_variant_data(&variant.data, variant.ident, generics, item_id, variant.span); - walk_list!(visitor, visit_anon_const, &variant.node.disr_expr); - walk_list!(visitor, visit_attribute, &variant.node.attrs); + walk_list!(visitor, visit_anon_const, &variant.disr_expr); + walk_list!(visitor, visit_attribute, &variant.attrs); } pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) { @@ -442,14 +442,11 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) { PatKind::Struct(ref path, ref fields, _) => { visitor.visit_path(path, pattern.id); for field in fields { - walk_list!(visitor, visit_attribute, field.node.attrs.iter()); - visitor.visit_ident(field.node.ident); - visitor.visit_pat(&field.node.pat) + walk_list!(visitor, visit_attribute, field.attrs.iter()); + visitor.visit_ident(field.ident); + visitor.visit_pat(&field.pat) } } - PatKind::Tuple(ref elems) => { - walk_list!(visitor, visit_pat, elems); - } PatKind::Box(ref subpattern) | PatKind::Ref(ref subpattern, _) | PatKind::Paren(ref subpattern) => { @@ -465,7 +462,9 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) { visitor.visit_expr(upper_bound); } PatKind::Wild | PatKind::Rest => {}, - PatKind::Slice(ref elems) => { + PatKind::Tuple(ref elems) + | PatKind::Slice(ref elems) + | PatKind::Or(ref elems) => { walk_list!(visitor, visit_pat, elems); } PatKind::Mac(ref mac) => visitor.visit_mac(mac), @@ -663,7 +662,7 @@ pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) { } pub fn walk_mac<'a, V: Visitor<'a>>(visitor: &mut V, mac: &'a Mac) { - visitor.visit_path(&mac.node.path, DUMMY_NODE_ID); + visitor.visit_path(&mac.path, DUMMY_NODE_ID); } pub fn walk_anon_const<'a, V: Visitor<'a>>(visitor: &mut V, constant: &'a AnonConst) { diff --git a/src/libsyntax_ext/asm.rs b/src/libsyntax_ext/asm.rs index c1c2732605c..644a44f1989 100644 --- a/src/libsyntax_ext/asm.rs +++ b/src/libsyntax_ext/asm.rs @@ -47,10 +47,10 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt<'_>, -> Box<dyn base::MacResult + 'cx> { let mut inline_asm = match parse_inline_asm(cx, sp, tts) { Ok(Some(inline_asm)) => inline_asm, - Ok(None) => return DummyResult::expr(sp), + Ok(None) => return DummyResult::any(sp), Err(mut err) => { err.emit(); - return DummyResult::expr(sp); + return DummyResult::any(sp); } }; @@ -63,7 +63,7 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt<'_>, MacEager::expr(P(ast::Expr { id: ast::DUMMY_NODE_ID, node: ast::ExprKind::InlineAsm(P(inline_asm)), - span: sp, + span: sp.with_ctxt(cx.backtrace()), attrs: ThinVec::new(), })) } @@ -277,6 +277,5 @@ fn parse_inline_asm<'a>( volatile, alignstack, dialect, - ctxt: cx.backtrace(), })) } diff --git a/src/libsyntax_ext/assert.rs b/src/libsyntax_ext/assert.rs index d7571f43edd..6301283460a 100644 --- a/src/libsyntax_ext/assert.rs +++ b/src/libsyntax_ext/assert.rs @@ -1,7 +1,6 @@ use errors::{Applicability, DiagnosticBuilder}; use syntax::ast::{self, *}; -use syntax::source_map::Spanned; use syntax::ext::base::*; use syntax::parse::token::{self, TokenKind}; use syntax::parse::parser::Parser; @@ -20,12 +19,12 @@ pub fn expand_assert<'cx>( Ok(assert) => assert, Err(mut err) => { err.emit(); - return DummyResult::expr(sp); + return DummyResult::any(sp); } }; let sp = sp.apply_mark(cx.current_expansion.id); - let panic_call = Mac_ { + let panic_call = Mac { path: Path::from_ident(Ident::new(sym::panic, sp)), tts: custom_message.unwrap_or_else(|| { TokenStream::from(TokenTree::token( @@ -37,6 +36,7 @@ pub fn expand_assert<'cx>( )) }).into(), delim: MacDelimiter::Parenthesis, + span: sp, prior_type_ascription: None, }; let if_expr = cx.expr_if( @@ -44,10 +44,7 @@ pub fn expand_assert<'cx>( cx.expr(sp, ExprKind::Unary(UnOp::Not, cond_expr)), cx.expr( sp, - ExprKind::Mac(Spanned { - span: sp, - node: panic_call, - }), + ExprKind::Mac(panic_call), ), None, ); diff --git a/src/libsyntax_ext/cfg.rs b/src/libsyntax_ext/cfg.rs index 84830e6ddda..0e52c1af908 100644 --- a/src/libsyntax_ext/cfg.rs +++ b/src/libsyntax_ext/cfg.rs @@ -25,7 +25,7 @@ pub fn expand_cfg( } Err(mut err) => { err.emit(); - DummyResult::expr(sp) + DummyResult::any(sp) } } } diff --git a/src/libsyntax_ext/concat.rs b/src/libsyntax_ext/concat.rs index f1d079eb053..4cd17531a45 100644 --- a/src/libsyntax_ext/concat.rs +++ b/src/libsyntax_ext/concat.rs @@ -1,5 +1,5 @@ use syntax::ast; -use syntax::ext::base; +use syntax::ext::base::{self, DummyResult}; use syntax::symbol::Symbol; use syntax::tokenstream; @@ -12,7 +12,7 @@ pub fn expand_syntax_ext( ) -> Box<dyn base::MacResult + 'static> { let es = match base::get_exprs_from_tts(cx, sp, tts) { Some(e) => e, - None => return base::DummyResult::expr(sp), + None => return DummyResult::any(sp), }; let mut accumulator = String::new(); let mut missing_literal = vec![]; @@ -55,9 +55,9 @@ pub fn expand_syntax_ext( let mut err = cx.struct_span_err(missing_literal, "expected a literal"); err.note("only literals (like `\"foo\"`, `42` and `3.14`) can be passed to `concat!()`"); err.emit(); - return base::DummyResult::expr(sp); + return DummyResult::any(sp); } else if has_errors { - return base::DummyResult::expr(sp); + return DummyResult::any(sp); } let sp = sp.apply_mark(cx.current_expansion.id); base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&accumulator))) diff --git a/src/libsyntax_ext/deriving/clone.rs b/src/libsyntax_ext/deriving/clone.rs index 3b1edf90d6b..d030ea4a56e 100644 --- a/src/libsyntax_ext/deriving/clone.rs +++ b/src/libsyntax_ext/deriving/clone.rs @@ -35,7 +35,7 @@ pub fn expand_deriving_clone(cx: &mut ExtCtxt<'_>, match annitem.node { ItemKind::Struct(_, Generics { ref params, .. }) | ItemKind::Enum(_, Generics { ref params, .. }) => { - let container_id = cx.current_expansion.id.parent(); + let container_id = cx.current_expansion.id.expn_data().parent; if cx.resolver.has_derives(container_id, SpecialDerives::COPY) && !params.iter().any(|param| match param.kind { ast::GenericParamKind::Type { .. } => true, @@ -129,7 +129,7 @@ fn cs_clone_shallow(name: &str, if is_union { // let _: AssertParamIsCopy<Self>; let self_ty = - cx.ty_path(cx.path_ident(trait_span, ast::Ident::with_empty_ctxt(kw::SelfUpper))); + cx.ty_path(cx.path_ident(trait_span, ast::Ident::with_dummy_span(kw::SelfUpper))); assert_ty_bounds(cx, &mut stmts, self_ty, trait_span, "AssertParamIsCopy"); } else { match *substr.fields { @@ -138,7 +138,7 @@ fn cs_clone_shallow(name: &str, } StaticEnum(enum_def, ..) => { for variant in &enum_def.variants { - process_variant(cx, &mut stmts, &variant.node.data); + process_variant(cx, &mut stmts, &variant.data); } } _ => cx.span_bug(trait_span, &format!("unexpected substructure in \ @@ -170,9 +170,9 @@ fn cs_clone(name: &str, vdata = vdata_; } EnumMatching(.., variant, ref af) => { - ctor_path = cx.path(trait_span, vec![substr.type_ident, variant.node.ident]); + ctor_path = cx.path(trait_span, vec![substr.type_ident, variant.ident]); all_fields = af; - vdata = &variant.node.data; + vdata = &variant.data; } EnumNonMatchingCollapsed(..) => { cx.span_bug(trait_span, diff --git a/src/libsyntax_ext/deriving/cmp/eq.rs b/src/libsyntax_ext/deriving/cmp/eq.rs index 1909729f4a9..54027c600b4 100644 --- a/src/libsyntax_ext/deriving/cmp/eq.rs +++ b/src/libsyntax_ext/deriving/cmp/eq.rs @@ -13,7 +13,7 @@ pub fn expand_deriving_eq(cx: &mut ExtCtxt<'_>, mitem: &MetaItem, item: &Annotatable, push: &mut dyn FnMut(Annotatable)) { - cx.resolver.add_derives(cx.current_expansion.id.parent(), SpecialDerives::EQ); + cx.resolver.add_derives(cx.current_expansion.id.expn_data().parent, SpecialDerives::EQ); let inline = cx.meta_word(span, sym::inline); let hidden = cx.meta_list_item_word(span, sym::hidden); @@ -75,7 +75,7 @@ fn cs_total_eq_assert(cx: &mut ExtCtxt<'_>, } StaticEnum(enum_def, ..) => { for variant in &enum_def.variants { - process_variant(cx, &mut stmts, &variant.node.data); + process_variant(cx, &mut stmts, &variant.data); } } _ => cx.span_bug(trait_span, "unexpected substructure in `derive(Eq)`") diff --git a/src/libsyntax_ext/deriving/cmp/ord.rs b/src/libsyntax_ext/deriving/cmp/ord.rs index 885cfee3565..55687c3175b 100644 --- a/src/libsyntax_ext/deriving/cmp/ord.rs +++ b/src/libsyntax_ext/deriving/cmp/ord.rs @@ -43,17 +43,18 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt<'_>, } -pub fn ordering_collapsed(cx: &mut ExtCtxt<'_>, - span: Span, - self_arg_tags: &[ast::Ident]) - -> P<ast::Expr> { +pub fn ordering_collapsed( + cx: &mut ExtCtxt<'_>, + span: Span, + self_arg_tags: &[ast::Ident], +) -> P<ast::Expr> { let lft = cx.expr_ident(span, self_arg_tags[0]); let rgt = cx.expr_addr_of(span, cx.expr_ident(span, self_arg_tags[1])); - cx.expr_method_call(span, lft, cx.ident_of("cmp"), vec![rgt]) + cx.expr_method_call(span, lft, ast::Ident::new(sym::cmp, span), vec![rgt]) } pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> P<Expr> { - let test_id = cx.ident_of("cmp").gensym(); + let test_id = ast::Ident::new(sym::cmp, span); let equals_path = cx.path_global(span, cx.std_path(&[sym::cmp, sym::Ordering, sym::Equal])); let cmp_path = cx.std_path(&[sym::cmp, sym::Ord, sym::cmp]); @@ -75,34 +76,34 @@ pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> P< // as the outermost one, and the last as the innermost. false, |cx, span, old, self_f, other_fs| { - // match new { - // ::std::cmp::Ordering::Equal => old, - // cmp => cmp - // } + // match new { + // ::std::cmp::Ordering::Equal => old, + // cmp => cmp + // } - let new = { - let other_f = match other_fs { - [o_f] => o_f, - _ => cx.span_bug(span, "not exactly 2 arguments in `derive(Ord)`"), - }; + let new = { + let other_f = match other_fs { + [o_f] => o_f, + _ => cx.span_bug(span, "not exactly 2 arguments in `derive(Ord)`"), + }; - let args = vec![ - cx.expr_addr_of(span, self_f), - cx.expr_addr_of(span, other_f.clone()), - ]; + let args = vec![ + cx.expr_addr_of(span, self_f), + cx.expr_addr_of(span, other_f.clone()), + ]; - cx.expr_call_global(span, cmp_path.clone(), args) - }; + cx.expr_call_global(span, cmp_path.clone(), args) + }; - let eq_arm = cx.arm(span, - vec![cx.pat_path(span, equals_path.clone())], - old); - let neq_arm = cx.arm(span, - vec![cx.pat_ident(span, test_id)], - cx.expr_ident(span, test_id)); + let eq_arm = cx.arm(span, + vec![cx.pat_path(span, equals_path.clone())], + old); + let neq_arm = cx.arm(span, + vec![cx.pat_ident(span, test_id)], + cx.expr_ident(span, test_id)); - cx.expr_match(span, new, vec![eq_arm, neq_arm]) - }, + cx.expr_match(span, new, vec![eq_arm, neq_arm]) + }, cx.expr_path(equals_path.clone()), Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| { if self_args.len() != 2 { diff --git a/src/libsyntax_ext/deriving/cmp/partial_eq.rs b/src/libsyntax_ext/deriving/cmp/partial_eq.rs index 7d7c4ae22a8..91e1e80e4fb 100644 --- a/src/libsyntax_ext/deriving/cmp/partial_eq.rs +++ b/src/libsyntax_ext/deriving/cmp/partial_eq.rs @@ -13,7 +13,7 @@ pub fn expand_deriving_partial_eq(cx: &mut ExtCtxt<'_>, mitem: &MetaItem, item: &Annotatable, push: &mut dyn FnMut(Annotatable)) { - cx.resolver.add_derives(cx.current_expansion.id.parent(), SpecialDerives::PARTIAL_EQ); + cx.resolver.add_derives(cx.current_expansion.id.expn_data().parent, SpecialDerives::PARTIAL_EQ); // structures are equal if all fields are equal, and non equal, if // any fields are not equal or if the enum variants are different diff --git a/src/libsyntax_ext/deriving/cmp/partial_ord.rs b/src/libsyntax_ext/deriving/cmp/partial_ord.rs index 0ec30f5924f..740b92a9b79 100644 --- a/src/libsyntax_ext/deriving/cmp/partial_ord.rs +++ b/src/libsyntax_ext/deriving/cmp/partial_ord.rs @@ -94,11 +94,12 @@ pub enum OrderingOp { GeOp, } -pub fn some_ordering_collapsed(cx: &mut ExtCtxt<'_>, - span: Span, - op: OrderingOp, - self_arg_tags: &[ast::Ident]) - -> P<ast::Expr> { +pub fn some_ordering_collapsed( + cx: &mut ExtCtxt<'_>, + span: Span, + op: OrderingOp, + self_arg_tags: &[ast::Ident], +) -> P<ast::Expr> { let lft = cx.expr_ident(span, self_arg_tags[0]); let rgt = cx.expr_addr_of(span, cx.expr_ident(span, self_arg_tags[1])); let op_str = match op { @@ -108,11 +109,11 @@ pub fn some_ordering_collapsed(cx: &mut ExtCtxt<'_>, GtOp => "gt", GeOp => "ge", }; - cx.expr_method_call(span, lft, cx.ident_of(op_str), vec![rgt]) + cx.expr_method_call(span, lft, ast::Ident::from_str_and_span(op_str, span), vec![rgt]) } pub fn cs_partial_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> P<Expr> { - let test_id = cx.ident_of("cmp").gensym(); + let test_id = ast::Ident::new(sym::cmp, span); let ordering = cx.path_global(span, cx.std_path(&[sym::cmp, sym::Ordering, sym::Equal])); let ordering_expr = cx.expr_path(ordering.clone()); let equals_expr = cx.expr_some(span, ordering_expr); diff --git a/src/libsyntax_ext/deriving/debug.rs b/src/libsyntax_ext/deriving/debug.rs index 0f709630bf4..44153541048 100644 --- a/src/libsyntax_ext/deriving/debug.rs +++ b/src/libsyntax_ext/deriving/debug.rs @@ -53,7 +53,7 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_> // based on the "shape". let (ident, vdata, fields) = match substr.fields { Struct(vdata, fields) => (substr.type_ident, *vdata, fields), - EnumMatching(_, _, v, fields) => (v.node.ident, &v.node.data, fields), + EnumMatching(_, _, v, fields) => (v.ident, &v.data, fields), EnumNonMatchingCollapsed(..) | StaticStruct(..) | StaticEnum(..) => cx.span_bug(span, "nonsensical .fields in `#[derive(Debug)]`"), @@ -62,7 +62,7 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_> // We want to make sure we have the ctxt set so that we can use unstable methods let span = span.with_ctxt(cx.backtrace()); let name = cx.expr_lit(span, ast::LitKind::Str(ident.name, ast::StrStyle::Cooked)); - let builder = Ident::from_str("debug_trait_builder").gensym(); + let builder = Ident::from_str_and_span("debug_trait_builder", span); let builder_expr = cx.expr_ident(span, builder.clone()); let fmt = substr.nonself_args[0].clone(); @@ -73,7 +73,7 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_> // tuple struct/"normal" variant let expr = cx.expr_method_call(span, fmt, Ident::from_str("debug_tuple"), vec![name]); - stmts.push(cx.stmt_let(DUMMY_SP, true, builder, expr)); + stmts.push(cx.stmt_let(span, true, builder, expr)); for field in fields { // Use double indirection to make sure this works for unsized types @@ -82,7 +82,7 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_> let expr = cx.expr_method_call(span, builder_expr.clone(), - Ident::with_empty_ctxt(sym::field), + Ident::new(sym::field, span), vec![field]); // Use `let _ = expr;` to avoid triggering the @@ -106,7 +106,7 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_> let field = cx.expr_addr_of(field.span, field); let expr = cx.expr_method_call(span, builder_expr.clone(), - Ident::with_empty_ctxt(sym::field), + Ident::new(sym::field, span), vec![name, field]); stmts.push(stmt_let_undescore(cx, span, expr)); } diff --git a/src/libsyntax_ext/deriving/decodable.rs b/src/libsyntax_ext/deriving/decodable.rs index 293c5a1e7e7..9b6f8518de0 100644 --- a/src/libsyntax_ext/deriving/decodable.rs +++ b/src/libsyntax_ext/deriving/decodable.rs @@ -1,6 +1,6 @@ -//! The compiler code necessary for `#[derive(Decodable)]`. See encodable.rs for more. +//! The compiler code necessary for `#[derive(RustcDecodable)]`. See encodable.rs for more. -use crate::deriving::{self, pathvec_std}; +use crate::deriving::pathvec_std; use crate::deriving::generic::*; use crate::deriving::generic::ty::*; @@ -17,7 +17,7 @@ pub fn expand_deriving_rustc_decodable(cx: &mut ExtCtxt<'_>, item: &Annotatable, push: &mut dyn FnMut(Annotatable)) { let krate = "rustc_serialize"; - let typaram = &*deriving::hygienic_type_parameter(item, "__D"); + let typaram = "__D"; let trait_def = TraitDef { span, diff --git a/src/libsyntax_ext/deriving/encodable.rs b/src/libsyntax_ext/deriving/encodable.rs index 6d0d3b96a56..8b18fb25e90 100644 --- a/src/libsyntax_ext/deriving/encodable.rs +++ b/src/libsyntax_ext/deriving/encodable.rs @@ -1,11 +1,12 @@ -//! The compiler code necessary to implement the `#[derive(Encodable)]` -//! (and `Decodable`, in `decodable.rs`) extension. The idea here is that -//! type-defining items may be tagged with `#[derive(Encodable, Decodable)]`. +//! The compiler code necessary to implement the `#[derive(RustcEncodable)]` +//! (and `RustcDecodable`, in `decodable.rs`) extension. The idea here is that +//! type-defining items may be tagged with +//! `#[derive(RustcEncodable, RustcDecodable)]`. //! //! For example, a type like: //! //! ``` -//! #[derive(Encodable, Decodable)] +//! #[derive(RustcEncodable, RustcDecodable)] //! struct Node { id: usize } //! ``` //! @@ -40,15 +41,17 @@ //! references other non-built-in types. A type definition like: //! //! ``` -//! # #[derive(Encodable, Decodable)] struct Span; -//! #[derive(Encodable, Decodable)] +//! # #[derive(RustcEncodable, RustcDecodable)] +//! # struct Span; +//! #[derive(RustcEncodable, RustcDecodable)] //! struct Spanned<T> { node: T, span: Span } //! ``` //! //! would yield functions like: //! //! ``` -//! # #[derive(Encodable, Decodable)] struct Span; +//! # #[derive(RustcEncodable, RustcDecodable)] +//! # struct Span; //! # struct Spanned<T> { node: T, span: Span } //! impl< //! S: Encoder<E>, @@ -82,7 +85,7 @@ //! } //! ``` -use crate::deriving::{self, pathvec_std}; +use crate::deriving::pathvec_std; use crate::deriving::generic::*; use crate::deriving::generic::ty::*; @@ -98,7 +101,7 @@ pub fn expand_deriving_rustc_encodable(cx: &mut ExtCtxt<'_>, item: &Annotatable, push: &mut dyn FnMut(Annotatable)) { let krate = "rustc_serialize"; - let typaram = &*deriving::hygienic_type_parameter(item, "__S"); + let typaram = "__S"; let trait_def = TraitDef { span, @@ -238,7 +241,7 @@ fn encodable_substructure(cx: &mut ExtCtxt<'_>, } let blk = cx.lambda_stmts_1(trait_span, stmts, blkarg); - let name = cx.expr_str(trait_span, variant.node.ident.name); + let name = cx.expr_str(trait_span, variant.ident.name); let call = cx.expr_method_call(trait_span, blkencoder, cx.ident_of("emit_enum_variant"), diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index 7e6d9126c87..1475bac0688 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -187,7 +187,7 @@ use syntax::ast::{self, BinOpKind, EnumDef, Expr, Generics, Ident, PatKind}; use syntax::ast::{VariantData, GenericParamKind, GenericArg}; use syntax::attr; use syntax::ext::base::{Annotatable, ExtCtxt, SpecialDerives}; -use syntax::source_map::{self, respan}; +use syntax::source_map::respan; use syntax::util::map_in_place::MapInPlace; use syntax::ptr::P; use syntax::symbol::{Symbol, kw, sym}; @@ -425,7 +425,7 @@ impl<'a> TraitDef<'a> { return; } }; - let container_id = cx.current_expansion.id.parent(); + let container_id = cx.current_expansion.id.expn_data().parent; let is_always_copy = cx.resolver.has_derives(container_id, SpecialDerives::COPY) && has_no_type_params; @@ -758,7 +758,7 @@ impl<'a> TraitDef<'a> { let mut field_tys = Vec::new(); for variant in &enum_def.variants { - field_tys.extend(variant.node + field_tys.extend(variant .data .fields() .iter() @@ -890,7 +890,7 @@ impl<'a> MethodDef<'a> { for (ty, name) in self.args.iter() { let ast_ty = ty.to_ty(cx, trait_.span, type_ident, generics); - let ident = cx.ident_of(name).gensym(); + let ident = ast::Ident::from_str_and_span(name, trait_.span); arg_tys.push((ident, ast_ty)); let arg_expr = cx.expr_ident(trait_.span, ident); @@ -928,7 +928,7 @@ impl<'a> MethodDef<'a> { let args = { let self_args = explicit_self.map(|explicit_self| { - let ident = Ident::with_empty_ctxt(kw::SelfLower).with_span_pos(trait_.span); + let ident = Ident::with_dummy_span(kw::SelfLower).with_span_pos(trait_.span); ast::Arg::from_self(ThinVec::default(), explicit_self, ident) }); let nonself_args = arg_types.into_iter() @@ -1210,7 +1210,7 @@ impl<'a> MethodDef<'a> { let vi_idents = self_arg_names.iter() .map(|name| { let vi_suffix = format!("{}_vi", &name[..]); - cx.ident_of(&vi_suffix[..]).gensym() + ast::Ident::from_str_and_span(&vi_suffix[..], trait_.span) }) .collect::<Vec<ast::Ident>>(); @@ -1220,7 +1220,7 @@ impl<'a> MethodDef<'a> { let catch_all_substructure = EnumNonMatchingCollapsed(self_arg_idents, &variants[..], &vi_idents[..]); - let first_fieldless = variants.iter().find(|v| v.node.data.fields().is_empty()); + let first_fieldless = variants.iter().find(|v| v.data.fields().is_empty()); // These arms are of the form: // (Variant1, Variant1, ...) => Body1 @@ -1229,7 +1229,7 @@ impl<'a> MethodDef<'a> { // where each tuple has length = self_args.len() let mut match_arms: Vec<ast::Arm> = variants.iter() .enumerate() - .filter(|&(_, v)| !(self.unify_fieldless_variants && v.node.data.fields().is_empty())) + .filter(|&(_, v)| !(self.unify_fieldless_variants && v.data.fields().is_empty())) .map(|(index, variant)| { let mk_self_pat = |cx: &mut ExtCtxt<'_>, self_arg_name: &str| { let (p, idents) = trait_.create_enum_variant_pattern(cx, @@ -1387,7 +1387,10 @@ impl<'a> MethodDef<'a> { let variant_value = deriving::call_intrinsic(cx, sp, "discriminant_value", vec![self_addr]); - let target_ty = cx.ty_ident(sp, cx.ident_of(target_type_name)); + let target_ty = cx.ty_ident( + sp, + ast::Ident::from_str_and_span(target_type_name, sp), + ); let variant_disr = cx.expr_cast(sp, variant_value, target_ty); let let_stmt = cx.stmt_let(sp, false, ident, variant_disr); index_let_stmts.push(let_stmt); @@ -1513,8 +1516,8 @@ impl<'a> MethodDef<'a> { .iter() .map(|v| { let sp = v.span.with_ctxt(trait_.span.ctxt()); - let summary = trait_.summarise_struct(cx, &v.node.data); - (v.node.ident, sp, summary) + let summary = trait_.summarise_struct(cx, &v.data); + (v.ident, sp, summary) }) .collect(); self.call_substructure_method(cx, @@ -1588,7 +1591,7 @@ impl<'a> TraitDef<'a> { let mut ident_exprs = Vec::new(); for (i, struct_field) in struct_def.fields().iter().enumerate() { let sp = struct_field.span.with_ctxt(self.span.ctxt()); - let ident = cx.ident_of(&format!("{}_{}", prefix, i)).gensym(); + let ident = ast::Ident::from_str_and_span(&format!("{}_{}", prefix, i), self.span); paths.push(ident.with_span_pos(sp)); let val = cx.expr_path(cx.path_ident(sp, ident)); let val = if use_temporaries { @@ -1610,14 +1613,13 @@ impl<'a> TraitDef<'a> { if ident.is_none() { cx.span_bug(sp, "a braced struct with unnamed fields in `derive`"); } - source_map::Spanned { + ast::FieldPat { + ident: ident.unwrap(), + is_shorthand: false, + attrs: ThinVec::new(), + id: ast::DUMMY_NODE_ID, span: pat.span.with_ctxt(self.span.ctxt()), - node: ast::FieldPat { - ident: ident.unwrap(), - pat, - is_shorthand: false, - attrs: ThinVec::new(), - }, + pat, } }) .collect(); @@ -1643,9 +1645,9 @@ impl<'a> TraitDef<'a> { mutbl: ast::Mutability) -> (P<ast::Pat>, Vec<(Span, Option<Ident>, P<Expr>, &'a [ast::Attribute])>) { let sp = variant.span.with_ctxt(self.span.ctxt()); - let variant_path = cx.path(sp, vec![enum_ident, variant.node.ident]); + let variant_path = cx.path(sp, vec![enum_ident, variant.ident]); let use_temporaries = false; // enums can't be repr(packed) - self.create_struct_pattern(cx, variant_path, &variant.node.data, prefix, mutbl, + self.create_struct_pattern(cx, variant_path, &variant.data, prefix, mutbl, use_temporaries) } } @@ -1776,7 +1778,7 @@ pub fn is_type_without_fields(item: &Annotatable) -> bool { if let Annotatable::Item(ref item) = *item { match item.node { ast::ItemKind::Enum(ref enum_def, _) => { - enum_def.variants.iter().all(|v| v.node.data.fields().is_empty()) + enum_def.variants.iter().all(|v| v.data.fields().is_empty()) } ast::ItemKind::Struct(ref variant_data, _) => variant_data.fields().is_empty(), _ => false, diff --git a/src/libsyntax_ext/deriving/generic/ty.rs b/src/libsyntax_ext/deriving/generic/ty.rs index 399829eaefd..7fcf036fc81 100644 --- a/src/libsyntax_ext/deriving/generic/ty.rs +++ b/src/libsyntax_ext/deriving/generic/ty.rs @@ -72,7 +72,7 @@ impl<'a> Path<'a> { self_ty: Ident, self_generics: &Generics) -> ast::Path { - let mut idents = self.path.iter().map(|s| cx.ident_of(*s)).collect(); + let mut idents = self.path.iter().map(|s| Ident::from_str_and_span(*s, span)).collect(); let lt = mk_lifetimes(cx, span, &self.lifetime); let tys: Vec<P<ast::Ty>> = self.params.iter().map(|t| t.to_ty(cx, span, self_ty, self_generics)).collect(); @@ -209,7 +209,7 @@ fn mk_ty_param(cx: &ExtCtxt<'_>, cx.trait_bound(path) }) .collect(); - cx.typaram(span, cx.ident_of(name), attrs.to_owned(), bounds, None) + cx.typaram(span, ast::Ident::from_str_and_span(name, span), attrs.to_owned(), bounds, None) } fn mk_generics(params: Vec<ast::GenericParam>, span: Span) -> Generics { diff --git a/src/libsyntax_ext/deriving/hash.rs b/src/libsyntax_ext/deriving/hash.rs index 9787722e81d..2fc594abd70 100644 --- a/src/libsyntax_ext/deriving/hash.rs +++ b/src/libsyntax_ext/deriving/hash.rs @@ -16,7 +16,7 @@ pub fn expand_deriving_hash(cx: &mut ExtCtxt<'_>, let path = Path::new_(pathvec_std!(cx, hash::Hash), None, vec![], PathKind::Std); - let typaram = &*deriving::hygienic_type_parameter(item, "__H"); + let typaram = "__H"; let arg = Path::new_local(typaram); let hash_trait_def = TraitDef { diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs index 8cd2853e538..da68eea0c50 100644 --- a/src/libsyntax_ext/deriving/mod.rs +++ b/src/libsyntax_ext/deriving/mod.rs @@ -54,33 +54,6 @@ impl MultiItemModifier for BuiltinDerive { } } -/// Construct a name for the inner type parameter that can't collide with any type parameters of -/// the item. This is achieved by starting with a base and then concatenating the names of all -/// other type parameters. -// FIXME(aburka): use real hygiene when that becomes possible -fn hygienic_type_parameter(item: &Annotatable, base: &str) -> String { - let mut typaram = String::from(base); - if let Annotatable::Item(ref item) = *item { - match item.node { - ast::ItemKind::Struct(_, ast::Generics { ref params, .. }) | - ast::ItemKind::Enum(_, ast::Generics { ref params, .. }) => { - for param in params { - match param.kind { - ast::GenericParamKind::Type { .. } => { - typaram.push_str(¶m.ident.as_str()); - } - _ => {} - } - } - } - - _ => {} - } - } - - typaram -} - /// Constructs an expression that calls an intrinsic fn call_intrinsic(cx: &ExtCtxt<'_>, span: Span, diff --git a/src/libsyntax_ext/env.rs b/src/libsyntax_ext/env.rs index 39fc90decc9..9834130fa23 100644 --- a/src/libsyntax_ext/env.rs +++ b/src/libsyntax_ext/env.rs @@ -16,20 +16,20 @@ pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt<'_>, tts: &[tokenstream::TokenTree]) -> Box<dyn base::MacResult + 'cx> { let var = match get_single_str_from_tts(cx, sp, tts, "option_env!") { - None => return DummyResult::expr(sp), + None => return DummyResult::any(sp), Some(v) => v, }; let sp = sp.apply_mark(cx.current_expansion.id); let e = match env::var(&*var.as_str()) { Err(..) => { - let lt = cx.lifetime(sp, Ident::with_empty_ctxt(kw::StaticLifetime)); + let lt = cx.lifetime(sp, Ident::with_dummy_span(kw::StaticLifetime)); cx.expr_path(cx.path_all(sp, true, cx.std_path(&[sym::option, sym::Option, sym::None]), vec![GenericArg::Type(cx.ty_rptr(sp, cx.ty_ident(sp, - Ident::with_empty_ctxt(sym::str)), + Ident::with_dummy_span(sym::str)), Some(lt), ast::Mutability::Immutable))], vec![])) @@ -50,21 +50,21 @@ pub fn expand_env<'cx>(cx: &'cx mut ExtCtxt<'_>, let mut exprs = match get_exprs_from_tts(cx, sp, tts) { Some(ref exprs) if exprs.is_empty() => { cx.span_err(sp, "env! takes 1 or 2 arguments"); - return DummyResult::expr(sp); + return DummyResult::any(sp); } - None => return DummyResult::expr(sp), + None => return DummyResult::any(sp), Some(exprs) => exprs.into_iter(), }; let var = match expr_to_string(cx, exprs.next().unwrap(), "expected string literal") { - None => return DummyResult::expr(sp), + None => return DummyResult::any(sp), Some((v, _style)) => v, }; let msg = match exprs.next() { None => Symbol::intern(&format!("environment variable `{}` not defined", var)), Some(second) => { match expr_to_string(cx, second, "expected string literal") { - None => return DummyResult::expr(sp), + None => return DummyResult::any(sp), Some((s, _style)) => s, } } @@ -72,13 +72,13 @@ pub fn expand_env<'cx>(cx: &'cx mut ExtCtxt<'_>, if exprs.next().is_some() { cx.span_err(sp, "env! takes 1 or 2 arguments"); - return DummyResult::expr(sp); + return DummyResult::any(sp); } let e = match env::var(&*var.as_str()) { Err(_) => { cx.span_err(sp, &msg.as_str()); - return DummyResult::expr(sp); + return DummyResult::any(sp); } Ok(s) => cx.expr_str(sp, Symbol::intern(&s)), }; diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 2ae13b66e28..83764205a19 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -805,7 +805,7 @@ fn expand_format_args_impl<'cx>( } Err(mut err) => { err.emit(); - DummyResult::expr(sp) + DummyResult::any(sp) } } } @@ -846,9 +846,9 @@ pub fn expand_preparsed_format_args( let msg = "format argument must be a string literal"; let fmt_sp = efmt.span; - let fmt = match expr_to_spanned_string(ecx, efmt, msg) { + let (fmt_str, fmt_style, fmt_span) = match expr_to_spanned_string(ecx, efmt, msg) { Ok(mut fmt) if append_newline => { - fmt.node.0 = Symbol::intern(&format!("{}\n", fmt.node.0)); + fmt.0 = Symbol::intern(&format!("{}\n", fmt.0)); fmt } Ok(fmt) => fmt, @@ -875,7 +875,7 @@ pub fn expand_preparsed_format_args( _ => (false, None), }; - let str_style = match fmt.node.1 { + let str_style = match fmt_style { ast::StrStyle::Cooked => None, ast::StrStyle::Raw(raw) => { Some(raw as usize) @@ -981,7 +981,7 @@ pub fn expand_preparsed_format_args( vec![] }; - let fmt_str = &*fmt.node.0.as_str(); // for the suggestions below + let fmt_str = &*fmt_str.as_str(); // for the suggestions below let mut parser = parse::Parser::new(fmt_str, str_style, skips, append_newline); let mut unverified_pieces = Vec::new(); @@ -995,7 +995,7 @@ pub fn expand_preparsed_format_args( if !parser.errors.is_empty() { let err = parser.errors.remove(0); - let sp = fmt.span.from_inner(err.span); + let sp = fmt_span.from_inner(err.span); let mut e = ecx.struct_span_err(sp, &format!("invalid format string: {}", err.description)); e.span_label(sp, err.label + " in format string"); @@ -1003,7 +1003,7 @@ pub fn expand_preparsed_format_args( e.note(¬e); } if let Some((label, span)) = err.secondary_label { - let sp = fmt.span.from_inner(span); + let sp = fmt_span.from_inner(span); e.span_label(sp, label); } e.emit(); @@ -1011,7 +1011,7 @@ pub fn expand_preparsed_format_args( } let arg_spans = parser.arg_places.iter() - .map(|span| fmt.span.from_inner(*span)) + .map(|span| fmt_span.from_inner(*span)) .collect(); let named_pos: FxHashSet<usize> = names.values().cloned().collect(); @@ -1034,7 +1034,7 @@ pub fn expand_preparsed_format_args( str_pieces: Vec::with_capacity(unverified_pieces.len()), all_pieces_simple: true, macsp, - fmtsp: fmt.span, + fmtsp: fmt_span, invalid_refs: Vec::new(), arg_spans, arg_with_formatting: Vec::new(), diff --git a/src/libsyntax_ext/global_allocator.rs b/src/libsyntax_ext/global_allocator.rs index f788b513804..d2121abe3b4 100644 --- a/src/libsyntax_ext/global_allocator.rs +++ b/src/libsyntax_ext/global_allocator.rs @@ -29,7 +29,7 @@ pub fn expand( }; // Generate a bunch of new items using the AllocFnFactory - let span = item.span.with_ctxt(SyntaxContext::empty().apply_mark(ecx.current_expansion.id)); + let span = item.span.with_ctxt(SyntaxContext::root().apply_mark(ecx.current_expansion.id)); let f = AllocFnFactory { span, kind: AllocatorKind::Global, @@ -44,7 +44,7 @@ pub fn expand( let const_ty = ecx.ty(span, TyKind::Tup(Vec::new())); let const_body = ecx.expr_block(ecx.block(span, stmts)); let const_item = - ecx.item_const(span, Ident::with_empty_ctxt(kw::Underscore), const_ty, const_body); + ecx.item_const(span, Ident::with_dummy_span(kw::Underscore), const_ty, const_body); // Return the original item and the new methods. vec![Annotatable::Item(item), Annotatable::Item(const_item)] @@ -120,7 +120,7 @@ impl AllocFnFactory<'_, '_> { ) -> P<Expr> { match *ty { AllocatorTy::Layout => { - let usize = self.cx.path_ident(self.span, Ident::with_empty_ctxt(sym::usize)); + let usize = self.cx.path_ident(self.span, Ident::with_dummy_span(sym::usize)); let ty_usize = self.cx.ty_path(usize); let size = ident(); let align = ident(); @@ -178,12 +178,12 @@ impl AllocFnFactory<'_, '_> { } fn usize(&self) -> P<Ty> { - let usize = self.cx.path_ident(self.span, Ident::with_empty_ctxt(sym::usize)); + let usize = self.cx.path_ident(self.span, Ident::with_dummy_span(sym::usize)); self.cx.ty_path(usize) } fn ptr_u8(&self) -> P<Ty> { - let u8 = self.cx.path_ident(self.span, Ident::with_empty_ctxt(sym::u8)); + let u8 = self.cx.path_ident(self.span, Ident::with_dummy_span(sym::u8)); let ty_u8 = self.cx.ty_path(u8); self.cx.ty_ptr(self.span, ty_u8, Mutability::Mutable) } diff --git a/src/libsyntax_ext/global_asm.rs b/src/libsyntax_ext/global_asm.rs index 112192fac5d..73ebeaec454 100644 --- a/src/libsyntax_ext/global_asm.rs +++ b/src/libsyntax_ext/global_asm.rs @@ -30,7 +30,7 @@ pub fn expand_global_asm<'cx>(cx: &'cx mut ExtCtxt<'_>, id: ast::DUMMY_NODE_ID, node: ast::ItemKind::GlobalAsm(P(global_asm)), vis: respan(sp.shrink_to_lo(), ast::VisibilityKind::Inherited), - span: sp, + span: sp.with_ctxt(cx.backtrace()), tokens: None, })]) } @@ -61,8 +61,5 @@ fn parse_global_asm<'a>( None => return Ok(None), }; - Ok(Some(ast::GlobalAsm { - asm, - ctxt: cx.backtrace(), - })) + Ok(Some(ast::GlobalAsm { asm })) } diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs index 0f3f5c0cd0e..4add2261c6c 100644 --- a/src/libsyntax_ext/lib.rs +++ b/src/libsyntax_ext/lib.rs @@ -42,7 +42,7 @@ pub mod test_harness; pub fn register_builtin_macros(resolver: &mut dyn syntax::ext::base::Resolver, edition: Edition) { let mut register = |name, kind| resolver.register_builtin_macro( - Ident::with_empty_ctxt(name), SyntaxExtension { + Ident::with_dummy_span(name), SyntaxExtension { is_builtin: true, ..SyntaxExtension::default(kind, edition) }, ); @@ -57,7 +57,6 @@ pub fn register_builtin_macros(resolver: &mut dyn syntax::ext::base::Resolver, e } register_bang! { - __rust_unstable_column: source_util::expand_column, asm: asm::expand_asm, assert: assert::expand_assert, cfg: cfg::expand_cfg, diff --git a/src/libsyntax_ext/plugin_macro_defs.rs b/src/libsyntax_ext/plugin_macro_defs.rs index a725f5e46ad..dbfd8fe98f3 100644 --- a/src/libsyntax_ext/plugin_macro_defs.rs +++ b/src/libsyntax_ext/plugin_macro_defs.rs @@ -11,7 +11,7 @@ use syntax::source_map::respan; use syntax::symbol::sym; use syntax::tokenstream::*; use syntax_pos::{Span, DUMMY_SP}; -use syntax_pos::hygiene::{ExpnId, ExpnInfo, ExpnKind, MacroKind}; +use syntax_pos::hygiene::{ExpnData, ExpnKind, MacroKind}; use std::mem; @@ -43,12 +43,12 @@ pub fn inject( ) { if !named_exts.is_empty() { let mut extra_items = Vec::new(); - let span = DUMMY_SP.fresh_expansion(ExpnId::root(), ExpnInfo::allow_unstable( + let span = DUMMY_SP.fresh_expansion(ExpnData::allow_unstable( ExpnKind::Macro(MacroKind::Attr, sym::plugin), DUMMY_SP, edition, [sym::rustc_attrs][..].into(), )); for (name, ext) in named_exts { - resolver.register_builtin_macro(Ident::with_empty_ctxt(name), ext); + resolver.register_builtin_macro(Ident::with_dummy_span(name), ext); extra_items.push(plugin_macro_def(name, span)); } // The `macro_rules` items must be inserted before any other items. diff --git a/src/libsyntax_ext/proc_macro_harness.rs b/src/libsyntax_ext/proc_macro_harness.rs index 7913a7442ed..e772eaf8349 100644 --- a/src/libsyntax_ext/proc_macro_harness.rs +++ b/src/libsyntax_ext/proc_macro_harness.rs @@ -1,18 +1,16 @@ use std::mem; +use smallvec::smallvec; use syntax::ast::{self, Ident}; use syntax::attr; -use syntax::source_map::{ExpnInfo, ExpnKind, respan}; +use syntax::source_map::{ExpnData, ExpnKind, respan}; use syntax::ext::base::{ExtCtxt, MacroKind}; -use syntax::ext::expand::ExpansionConfig; -use syntax::ext::hygiene::ExpnId; +use syntax::ext::expand::{AstFragment, ExpansionConfig}; use syntax::ext::proc_macro::is_proc_macro_attr; -use syntax::mut_visit::MutVisitor; use syntax::parse::ParseSess; use syntax::ptr::P; use syntax::symbol::{kw, sym}; use syntax::visit::{self, Visitor}; - use syntax_pos::{Span, DUMMY_SP}; struct ProcMacroDerive { @@ -329,7 +327,7 @@ fn mk_decls( custom_attrs: &[ProcMacroDef], custom_macros: &[ProcMacroDef], ) -> P<ast::Item> { - let span = DUMMY_SP.fresh_expansion(ExpnId::root(), ExpnInfo::allow_unstable( + let span = DUMMY_SP.fresh_expansion(ExpnData::allow_unstable( ExpnKind::Macro(MacroKind::Attr, sym::proc_macro), DUMMY_SP, cx.parse_sess.edition, [sym::rustc_attrs, sym::proc_macro_internals][..].into(), )); @@ -338,7 +336,7 @@ fn mk_decls( let doc = cx.meta_list(span, sym::doc, vec![hidden]); let doc_hidden = cx.attribute(doc); - let proc_macro = Ident::with_empty_ctxt(sym::proc_macro); + let proc_macro = Ident::with_dummy_span(sym::proc_macro); let krate = cx.item(span, proc_macro, Vec::new(), @@ -350,7 +348,7 @@ fn mk_decls( let custom_derive = Ident::from_str("custom_derive"); let attr = Ident::from_str("attr"); let bang = Ident::from_str("bang"); - let crate_kw = Ident::with_empty_ctxt(kw::Crate); + let crate_kw = Ident::with_dummy_span(kw::Crate); let decls = { let local_path = |sp: Span, name| { @@ -409,5 +407,7 @@ fn mk_decls( i }); - cx.monotonic_expander().flat_map_item(module).pop().unwrap() + // Integrate the new module into existing module structures. + let module = AstFragment::Items(smallvec![module]); + cx.monotonic_expander().fully_expand_fragment(module).make_items().pop().unwrap() } diff --git a/src/libsyntax_ext/source_util.rs b/src/libsyntax_ext/source_util.rs index 2c8d53a2315..e008ed710e4 100644 --- a/src/libsyntax_ext/source_util.rs +++ b/src/libsyntax_ext/source_util.rs @@ -9,8 +9,6 @@ use syntax::tokenstream; use smallvec::SmallVec; use syntax_pos::{self, Pos, Span}; -use std::fs; -use std::io::ErrorKind; use rustc_data_structures::sync::Lrc; // These macros all relate to the file system; they either return @@ -111,26 +109,23 @@ pub fn expand_include_str(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::To -> Box<dyn base::MacResult+'static> { let file = match get_single_str_from_tts(cx, sp, tts, "include_str!") { Some(f) => f, - None => return DummyResult::expr(sp) + None => return DummyResult::any(sp) }; let file = cx.resolve_path(file, sp); - match fs::read_to_string(&file) { - Ok(src) => { - let interned_src = Symbol::intern(&src); - - // Add this input file to the code map to make it available as - // dependency information - cx.source_map().new_source_file(file.into(), src); - - base::MacEager::expr(cx.expr_str(sp, interned_src)) + match cx.source_map().load_binary_file(&file) { + Ok(bytes) => match std::str::from_utf8(&bytes) { + Ok(src) => { + let interned_src = Symbol::intern(&src); + base::MacEager::expr(cx.expr_str(sp, interned_src)) + } + Err(_) => { + cx.span_err(sp, &format!("{} wasn't a utf-8 file", file.display())); + DummyResult::any(sp) + } }, - Err(ref e) if e.kind() == ErrorKind::InvalidData => { - cx.span_err(sp, &format!("{} wasn't a utf-8 file", file.display())); - DummyResult::expr(sp) - } Err(e) => { cx.span_err(sp, &format!("couldn't read {}: {}", file.display(), e)); - DummyResult::expr(sp) + DummyResult::any(sp) } } } @@ -139,26 +134,16 @@ pub fn expand_include_bytes(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream:: -> Box<dyn base::MacResult+'static> { let file = match get_single_str_from_tts(cx, sp, tts, "include_bytes!") { Some(f) => f, - None => return DummyResult::expr(sp) + None => return DummyResult::any(sp) }; let file = cx.resolve_path(file, sp); - match fs::read(&file) { + match cx.source_map().load_binary_file(&file) { Ok(bytes) => { - // Add the contents to the source map if it contains UTF-8. - let (contents, bytes) = match String::from_utf8(bytes) { - Ok(s) => { - let bytes = s.as_bytes().to_owned(); - (s, bytes) - }, - Err(e) => (String::new(), e.into_bytes()), - }; - cx.source_map().new_source_file(file.into(), contents); - base::MacEager::expr(cx.expr_lit(sp, ast::LitKind::ByteStr(Lrc::new(bytes)))) }, Err(e) => { cx.span_err(sp, &format!("couldn't read {}: {}", file.display(), e)); - DummyResult::expr(sp) + DummyResult::any(sp) } } } diff --git a/src/libsyntax_ext/standard_library_imports.rs b/src/libsyntax_ext/standard_library_imports.rs index 68b13bdd171..8ca376341fc 100644 --- a/src/libsyntax_ext/standard_library_imports.rs +++ b/src/libsyntax_ext/standard_library_imports.rs @@ -1,8 +1,8 @@ use syntax::{ast, attr}; use syntax::edition::Edition; -use syntax::ext::hygiene::{ExpnId, MacroKind}; +use syntax::ext::hygiene::MacroKind; use syntax::ptr::P; -use syntax::source_map::{ExpnInfo, ExpnKind, dummy_spanned, respan}; +use syntax::source_map::{ExpnData, ExpnKind, dummy_spanned, respan}; use syntax::symbol::{Ident, Symbol, kw, sym}; use syntax_pos::DUMMY_SP; @@ -32,7 +32,7 @@ pub fn inject( // HACK(eddyb) gensym the injected crates on the Rust 2018 edition, // so they don't accidentally interfere with the new import paths. let orig_name_sym = Symbol::intern(orig_name_str); - let orig_name_ident = Ident::with_empty_ctxt(orig_name_sym); + let orig_name_ident = Ident::with_dummy_span(orig_name_sym); let (rename, orig_name) = if rust_2018 { (orig_name_ident.gensym(), Some(orig_name_sym)) } else { @@ -40,7 +40,7 @@ pub fn inject( }; krate.module.items.insert(0, P(ast::Item { attrs: vec![attr::mk_attr_outer( - attr::mk_word_item(ast::Ident::with_empty_ctxt(sym::macro_use)) + attr::mk_word_item(ast::Ident::with_dummy_span(sym::macro_use)) )], vis: dummy_spanned(ast::VisibilityKind::Inherited), node: ast::ItemKind::ExternCrate(alt_std_name.or(orig_name)), @@ -55,7 +55,7 @@ pub fn inject( // the prelude. let name = names[0]; - let span = DUMMY_SP.fresh_expansion(ExpnId::root(), ExpnInfo::allow_unstable( + let span = DUMMY_SP.fresh_expansion(ExpnData::allow_unstable( ExpnKind::Macro(MacroKind::Attr, sym::std_inject), DUMMY_SP, edition, [sym::prelude_import][..].into(), )); @@ -66,7 +66,7 @@ pub fn inject( vis: respan(span.shrink_to_lo(), ast::VisibilityKind::Inherited), node: ast::ItemKind::Use(P(ast::UseTree { prefix: ast::Path { - segments: iter::once(ast::Ident::with_empty_ctxt(kw::PathRoot)) + segments: iter::once(ast::Ident::with_dummy_span(kw::PathRoot)) .chain( [name, "prelude", "v1"].iter().cloned() .map(ast::Ident::from_str) diff --git a/src/libsyntax_ext/test.rs b/src/libsyntax_ext/test.rs index 993ef257527..08582e714cc 100644 --- a/src/libsyntax_ext/test.rs +++ b/src/libsyntax_ext/test.rs @@ -29,7 +29,7 @@ pub fn expand_test_case( if !ecx.ecfg.should_test { return vec![]; } - let sp = attr_sp.with_ctxt(SyntaxContext::empty().apply_mark(ecx.current_expansion.id)); + let sp = attr_sp.with_ctxt(SyntaxContext::root().apply_mark(ecx.current_expansion.id)); let mut item = anno_item.expect_item(); item = item.map(|mut item| { item.vis = respan(item.vis.span, ast::VisibilityKind::Public); @@ -93,7 +93,7 @@ pub fn expand_test_or_bench( return vec![Annotatable::Item(item)]; } - let ctxt = SyntaxContext::empty().apply_mark(cx.current_expansion.id); + let ctxt = SyntaxContext::root().apply_mark(cx.current_expansion.id); let (sp, attr_sp) = (item.span.with_ctxt(ctxt), attr_sp.with_ctxt(ctxt)); // Gensym "test" so we can extern crate without conflicting with any local names diff --git a/src/libsyntax_ext/test_harness.rs b/src/libsyntax_ext/test_harness.rs index eec8a3f8023..4a6ea0ebf85 100644 --- a/src/libsyntax_ext/test_harness.rs +++ b/src/libsyntax_ext/test_harness.rs @@ -5,14 +5,13 @@ use smallvec::{smallvec, SmallVec}; use syntax::ast::{self, Ident}; use syntax::attr; use syntax::entry::{self, EntryPointType}; -use syntax::ext::base::{ExtCtxt, Resolver}; -use syntax::ext::expand::ExpansionConfig; -use syntax::ext::hygiene::{ExpnId, MacroKind}; +use syntax::ext::base::{ExtCtxt, MacroKind, Resolver}; +use syntax::ext::expand::{AstFragment, ExpansionConfig}; use syntax::feature_gate::Features; use syntax::mut_visit::{*, ExpectOne}; use syntax::parse::ParseSess; use syntax::ptr::P; -use syntax::source_map::{ExpnInfo, ExpnKind, dummy_spanned}; +use syntax::source_map::{ExpnData, ExpnKind, dummy_spanned}; use syntax::symbol::{kw, sym, Symbol}; use syntax_pos::{Span, DUMMY_SP}; @@ -74,12 +73,7 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> { noop_visit_crate(c, self); // Create a main function to run our tests - let test_main = { - let unresolved = mk_main(&mut self.cx); - self.cx.ext_cx.monotonic_expander().flat_map_item(unresolved).pop().unwrap() - }; - - c.module.items.push(test_main); + c.module.items.push(mk_main(&mut self.cx)); } fn flat_map_item(&mut self, i: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> { @@ -155,7 +149,7 @@ impl MutVisitor for EntryPointCleaner { EntryPointType::MainAttr | EntryPointType::Start => item.map(|ast::Item {id, ident, attrs, node, vis, span, tokens}| { - let allow_ident = Ident::with_empty_ctxt(sym::allow); + let allow_ident = Ident::with_dummy_span(sym::allow); let dc_nested = attr::mk_nested_word_item(Ident::from_str("dead_code")); let allow_dead_code_item = attr::mk_list_item(allow_ident, vec![dc_nested]); let allow_dead_code = attr::mk_attr_outer(allow_dead_code_item); @@ -196,7 +190,7 @@ fn mk_reexport_mod(cx: &mut TestCtxt<'_>, tests: Vec<Ident>, tested_submods: Vec<(Ident, Ident)>) -> (P<ast::Item>, Ident) { - let super_ = Ident::with_empty_ctxt(kw::Super); + let super_ = Ident::with_dummy_span(kw::Super); let items = tests.into_iter().map(|r| { cx.ext_cx.item_use_simple(DUMMY_SP, dummy_spanned(ast::VisibilityKind::Public), @@ -216,7 +210,7 @@ fn mk_reexport_mod(cx: &mut TestCtxt<'_>, let name = Ident::from_str("__test_reexports").gensym(); let parent = if parent == ast::DUMMY_NODE_ID { ast::CRATE_NODE_ID } else { parent }; cx.ext_cx.current_expansion.id = cx.ext_cx.resolver.get_module_scope(parent); - let it = cx.ext_cx.monotonic_expander().flat_map_item(P(ast::Item { + let module = P(ast::Item { ident: name, attrs: Vec::new(), id: ast::DUMMY_NODE_ID, @@ -224,9 +218,14 @@ fn mk_reexport_mod(cx: &mut TestCtxt<'_>, vis: dummy_spanned(ast::VisibilityKind::Public), span: DUMMY_SP, tokens: None, - })).pop().unwrap(); + }); - (it, name) + // Integrate the new module into existing module structures. + let module = AstFragment::Items(smallvec![module]); + let module = + cx.ext_cx.monotonic_expander().fully_expand_fragment(module).make_items().pop().unwrap(); + + (module, name) } /// Crawl over the crate, inserting test reexports and the test main function @@ -269,12 +268,12 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> { // #![main] // test::test_main_static(&[..tests]); // } - let sp = DUMMY_SP.fresh_expansion(ExpnId::root(), ExpnInfo::allow_unstable( + let sp = DUMMY_SP.fresh_expansion(ExpnData::allow_unstable( ExpnKind::Macro(MacroKind::Attr, sym::test_case), DUMMY_SP, cx.ext_cx.parse_sess.edition, [sym::main, sym::test, sym::rustc_attrs][..].into(), )); let ecx = &cx.ext_cx; - let test_id = Ident::with_empty_ctxt(sym::test); + let test_id = Ident::with_dummy_span(sym::test); // test::test_main_static(...) let mut test_runner = cx.test_runner.clone().unwrap_or( @@ -321,7 +320,7 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> { None => Ident::from_str_and_span("main", sp).gensym(), }; - P(ast::Item { + let main = P(ast::Item { ident: main_id, attrs: vec![main_attr], id: ast::DUMMY_NODE_ID, @@ -329,8 +328,11 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> { vis: dummy_spanned(ast::VisibilityKind::Public), span: sp, tokens: None, - }) + }); + // Integrate the new item into existing module structures. + let main = AstFragment::Items(smallvec![main]); + cx.ext_cx.monotonic_expander().fully_expand_fragment(main).make_items().pop().unwrap() } fn path_name_i(idents: &[Ident]) -> String { diff --git a/src/libsyntax_pos/edition.rs b/src/libsyntax_pos/edition.rs index 20216568426..00cd00f2837 100644 --- a/src/libsyntax_pos/edition.rs +++ b/src/libsyntax_pos/edition.rs @@ -1,7 +1,6 @@ use crate::symbol::{Symbol, sym}; use std::fmt; use std::str::FromStr; -use crate::GLOBALS; /// The edition of the compiler (RFC 2052) #[derive(Clone, Copy, Hash, PartialEq, PartialOrd, Debug, RustcEncodable, RustcDecodable, Eq)] @@ -39,10 +38,6 @@ impl fmt::Display for Edition { } impl Edition { - pub fn from_session() -> Edition { - GLOBALS.with(|globals| globals.edition) - } - pub fn lint_name(&self) -> &'static str { match *self { Edition::Edition2015 => "rust_2015_compatibility", diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs index f91a2291544..ebfb0764fa2 100644 --- a/src/libsyntax_pos/hygiene.rs +++ b/src/libsyntax_pos/hygiene.rs @@ -13,8 +13,8 @@ // // This explains why `HygieneData`, `SyntaxContext` and `ExpnId` have interfaces // with a certain amount of redundancy in them. For example, -// `SyntaxContext::outer_expn_info` combines `SyntaxContext::outer` and -// `ExpnId::expn_info` so that two `HygieneData` accesses can be performed within +// `SyntaxContext::outer_expn_data` combines `SyntaxContext::outer` and +// `ExpnId::expn_data` so that two `HygieneData` accesses can be performed within // a single `HygieneData::with` call. // // It also explains why many functions appear in `HygieneData` and again in @@ -56,16 +56,6 @@ struct SyntaxContextData { #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] pub struct ExpnId(u32); -// FIXME: Find a way to merge this with `ExpnInfo`. -#[derive(Debug)] -struct InternalExpnData { - parent: ExpnId, - /// Each expansion should have an associated expansion info, but sometimes there's a delay - /// between creation of an expansion ID and obtaining its info (e.g. macros are collected - /// first and then resolved later), so we use an `Option` here. - expn_info: Option<ExpnInfo>, -} - /// A property of a macro expansion that determines how identifiers /// produced by that expansion are resolved. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Hash, Debug, RustcEncodable, RustcDecodable)] @@ -86,8 +76,8 @@ pub enum Transparency { } impl ExpnId { - pub fn fresh(parent: ExpnId, expn_info: Option<ExpnInfo>) -> Self { - HygieneData::with(|data| data.fresh_expn(parent, expn_info)) + pub fn fresh(expn_data: Option<ExpnData>) -> Self { + HygieneData::with(|data| data.fresh_expn(expn_data)) } /// The ID of the theoretical expansion that generates freshly parsed, unexpanded AST. @@ -107,21 +97,16 @@ impl ExpnId { } #[inline] - pub fn parent(self) -> ExpnId { - HygieneData::with(|data| data.parent_expn(self)) - } - - #[inline] - pub fn expn_info(self) -> Option<ExpnInfo> { - HygieneData::with(|data| data.expn_info(self).cloned()) + pub fn expn_data(self) -> ExpnData { + HygieneData::with(|data| data.expn_data(self).clone()) } #[inline] - pub fn set_expn_info(self, info: ExpnInfo) { + pub fn set_expn_data(self, expn_data: ExpnData) { HygieneData::with(|data| { - let old_info = &mut data.expn_data[self.0 as usize].expn_info; - assert!(old_info.is_none(), "expansion info is reset for an expansion ID"); - *old_info = Some(info); + let old_expn_data = &mut data.expn_data[self.0 as usize]; + assert!(old_expn_data.is_none(), "expansion data is reset for an expansion ID"); + *old_expn_data = Some(expn_data); }) } @@ -139,12 +124,9 @@ impl ExpnId { #[inline] pub fn looks_like_proc_macro_derive(self) -> bool { HygieneData::with(|data| { - if data.default_transparency(self) == Transparency::Opaque { - if let Some(expn_info) = data.expn_info(self) { - if let ExpnKind::Macro(MacroKind::Derive, _) = expn_info.kind { - return true; - } - } + let expn_data = data.expn_data(self); + if let ExpnKind::Macro(MacroKind::Derive, _) = expn_data.kind { + return expn_data.default_transparency == Transparency::Opaque; } false }) @@ -153,7 +135,10 @@ impl ExpnId { #[derive(Debug)] crate struct HygieneData { - expn_data: Vec<InternalExpnData>, + /// Each expansion should have an associated expansion data, but sometimes there's a delay + /// between creation of an expansion ID and obtaining its data (e.g. macros are collected + /// first and then resolved later), so we use an `Option` here. + expn_data: Vec<Option<ExpnData>>, syntax_context_data: Vec<SyntaxContextData>, syntax_context_map: FxHashMap<(SyntaxContext, ExpnId, Transparency), SyntaxContext>, } @@ -161,10 +146,7 @@ crate struct HygieneData { impl HygieneData { crate fn new(edition: Edition) -> Self { HygieneData { - expn_data: vec![InternalExpnData { - parent: ExpnId::root(), - expn_info: Some(ExpnInfo::default(ExpnKind::Root, DUMMY_SP, edition)), - }], + expn_data: vec![Some(ExpnData::default(ExpnKind::Root, DUMMY_SP, edition))], syntax_context_data: vec![SyntaxContextData { outer_expn: ExpnId::root(), outer_transparency: Transparency::Opaque, @@ -181,25 +163,14 @@ impl HygieneData { GLOBALS.with(|globals| f(&mut *globals.hygiene_data.borrow_mut())) } - fn fresh_expn(&mut self, parent: ExpnId, expn_info: Option<ExpnInfo>) -> ExpnId { - self.expn_data.push(InternalExpnData { parent, expn_info }); + fn fresh_expn(&mut self, expn_data: Option<ExpnData>) -> ExpnId { + self.expn_data.push(expn_data); ExpnId(self.expn_data.len() as u32 - 1) } - fn parent_expn(&self, expn_id: ExpnId) -> ExpnId { - self.expn_data[expn_id.0 as usize].parent - } - - fn expn_info(&self, expn_id: ExpnId) -> Option<&ExpnInfo> { - if expn_id != ExpnId::root() { - Some(self.expn_data[expn_id.0 as usize].expn_info.as_ref() - .expect("no expansion info for an expansion ID")) - } else { - // FIXME: Some code relies on `expn_info().is_none()` meaning "no expansion". - // Introduce a method for checking for "no expansion" instead and always return - // `ExpnInfo` from this function instead of the `Option`. - None - } + fn expn_data(&self, expn_id: ExpnId) -> &ExpnData { + self.expn_data[expn_id.0 as usize].as_ref() + .expect("no expansion data for an expansion ID") } fn is_descendant_of(&self, mut expn_id: ExpnId, ancestor: ExpnId) -> bool { @@ -207,17 +178,11 @@ impl HygieneData { if expn_id == ExpnId::root() { return false; } - expn_id = self.parent_expn(expn_id); + expn_id = self.expn_data(expn_id).parent; } true } - fn default_transparency(&self, expn_id: ExpnId) -> Transparency { - self.expn_info(expn_id).map_or( - Transparency::SemiTransparent, |einfo| einfo.default_transparency - ) - } - fn modern(&self, ctxt: SyntaxContext) -> SyntaxContext { self.syntax_context_data[ctxt.0 as usize].opaque } @@ -246,7 +211,7 @@ impl HygieneData { fn marks(&self, mut ctxt: SyntaxContext) -> Vec<(ExpnId, Transparency)> { let mut marks = Vec::new(); - while ctxt != SyntaxContext::empty() { + while ctxt != SyntaxContext::root() { marks.push((self.outer_expn(ctxt), self.outer_transparency(ctxt))); ctxt = self.parent_ctxt(ctxt); } @@ -255,12 +220,8 @@ impl HygieneData { } fn walk_chain(&self, mut span: Span, to: SyntaxContext) -> Span { - while span.ctxt() != crate::NO_EXPANSION && span.ctxt() != to { - if let Some(info) = self.expn_info(self.outer_expn(span.ctxt())) { - span = info.call_site; - } else { - break; - } + while span.from_expansion() && span.ctxt() != to { + span = self.expn_data(self.outer_expn(span.ctxt())).call_site; } span } @@ -275,7 +236,9 @@ impl HygieneData { fn apply_mark(&mut self, ctxt: SyntaxContext, expn_id: ExpnId) -> SyntaxContext { assert_ne!(expn_id, ExpnId::root()); - self.apply_mark_with_transparency(ctxt, expn_id, self.default_transparency(expn_id)) + self.apply_mark_with_transparency( + ctxt, expn_id, self.expn_data(expn_id).default_transparency + ) } fn apply_mark_with_transparency(&mut self, ctxt: SyntaxContext, expn_id: ExpnId, @@ -285,15 +248,14 @@ impl HygieneData { return self.apply_mark_internal(ctxt, expn_id, transparency); } - let call_site_ctxt = - self.expn_info(expn_id).map_or(SyntaxContext::empty(), |info| info.call_site.ctxt()); + let call_site_ctxt = self.expn_data(expn_id).call_site.ctxt(); let mut call_site_ctxt = if transparency == Transparency::SemiTransparent { self.modern(call_site_ctxt) } else { self.modern_and_legacy(call_site_ctxt) }; - if call_site_ctxt == SyntaxContext::empty() { + if call_site_ctxt == SyntaxContext::root() { return self.apply_mark_internal(ctxt, expn_id, transparency); } @@ -400,7 +362,7 @@ pub fn update_dollar_crate_names(mut get_name: impl FnMut(SyntaxContext) -> Symb impl SyntaxContext { #[inline] - pub const fn empty() -> Self { + pub const fn root() -> Self { SyntaxContext(0) } @@ -578,20 +540,20 @@ impl SyntaxContext { HygieneData::with(|data| data.outer_expn(self)) } - /// `ctxt.outer_expn_info()` is equivalent to but faster than - /// `ctxt.outer_expn().expn_info()`. + /// `ctxt.outer_expn_data()` is equivalent to but faster than + /// `ctxt.outer_expn().expn_data()`. #[inline] - pub fn outer_expn_info(self) -> Option<ExpnInfo> { - HygieneData::with(|data| data.expn_info(data.outer_expn(self)).cloned()) + pub fn outer_expn_data(self) -> ExpnData { + HygieneData::with(|data| data.expn_data(data.outer_expn(self)).clone()) } - /// `ctxt.outer_expn_with_info()` is equivalent to but faster than - /// `{ let outer = ctxt.outer_expn(); (outer, outer.expn_info()) }`. + /// `ctxt.outer_expn_with_data()` is equivalent to but faster than + /// `{ let outer = ctxt.outer_expn(); (outer, outer.expn_data()) }`. #[inline] - pub fn outer_expn_with_info(self) -> (ExpnId, Option<ExpnInfo>) { + pub fn outer_expn_with_data(self) -> (ExpnId, ExpnData) { HygieneData::with(|data| { let outer = data.outer_expn(self); - (outer, data.expn_info(outer).cloned()) + (outer, data.expn_data(outer).clone()) }) } @@ -612,10 +574,10 @@ impl Span { /// other compiler-generated code to set per-span properties like allowed unstable features. /// The returned span belongs to the created expansion and has the new properties, /// but its location is inherited from the current span. - pub fn fresh_expansion(self, parent: ExpnId, expn_info: ExpnInfo) -> Span { + pub fn fresh_expansion(self, expn_data: ExpnData) -> Span { HygieneData::with(|data| { - let expn_id = data.fresh_expn(parent, Some(expn_info)); - self.with_ctxt(data.apply_mark(SyntaxContext::empty(), expn_id)) + let expn_id = data.fresh_expn(Some(expn_data)); + self.with_ctxt(data.apply_mark(SyntaxContext::root(), expn_id)) }) } } @@ -623,8 +585,12 @@ impl Span { /// A subset of properties from both macro definition and macro call available through global data. /// Avoid using this if you have access to the original definition or call structures. #[derive(Clone, Debug, RustcEncodable, RustcDecodable)] -pub struct ExpnInfo { +pub struct ExpnData { // --- The part unique to each expansion. + /// The kind of this expansion - macro or compiler desugaring. + pub kind: ExpnKind, + /// The expansion that produced this expansion. + pub parent: ExpnId, /// The location of the actual macro invocation or syntax sugar , e.g. /// `let x = foo!();` or `if let Some(y) = x {}` /// @@ -632,18 +598,18 @@ pub struct ExpnInfo { /// `foo!()` invoked `bar!()` internally, and there was an /// expression inside `bar!`; the call_site of the expression in /// the expansion would point to the `bar!` invocation; that - /// call_site span would have its own ExpnInfo, with the call_site + /// call_site span would have its own ExpnData, with the call_site /// pointing to the `foo!` invocation. pub call_site: Span, - /// The kind of this expansion - macro or compiler desugaring. - pub kind: ExpnKind, // --- The part specific to the macro/desugaring definition. - // --- FIXME: Share it between expansions with the same definition. + // --- It may be reasonable to share this part between expansions with the same definition, + // --- but such sharing is known to bring some minor inconveniences without also bringing + // --- noticeable perf improvements (PR #62898). /// The span of the macro definition (possibly dummy). /// This span serves only informational purpose and is not used for resolution. pub def_site: Span, - /// Transparency used by `apply_mark` for the expansion with this expansion info by default. + /// Transparency used by `apply_mark` for the expansion with this expansion data by default. pub default_transparency: Transparency, /// List of #[unstable]/feature-gated features that the macro is allowed to use /// internally without forcing the whole crate to opt-in @@ -659,12 +625,13 @@ pub struct ExpnInfo { pub edition: Edition, } -impl ExpnInfo { - /// Constructs an expansion info with default properties. - pub fn default(kind: ExpnKind, call_site: Span, edition: Edition) -> ExpnInfo { - ExpnInfo { - call_site, +impl ExpnData { + /// Constructs expansion data with default properties. + pub fn default(kind: ExpnKind, call_site: Span, edition: Edition) -> ExpnData { + ExpnData { kind, + parent: ExpnId::root(), + call_site, def_site: DUMMY_SP, default_transparency: Transparency::SemiTransparent, allow_internal_unstable: None, @@ -675,12 +642,17 @@ impl ExpnInfo { } pub fn allow_unstable(kind: ExpnKind, call_site: Span, edition: Edition, - allow_internal_unstable: Lrc<[Symbol]>) -> ExpnInfo { - ExpnInfo { + allow_internal_unstable: Lrc<[Symbol]>) -> ExpnData { + ExpnData { allow_internal_unstable: Some(allow_internal_unstable), - ..ExpnInfo::default(kind, call_site, edition) + ..ExpnData::default(kind, call_site, edition) } } + + #[inline] + pub fn is_root(&self) -> bool { + if let ExpnKind::Root = self.kind { true } else { false } + } } /// Expansion kind. @@ -767,14 +739,14 @@ impl DesugaringKind { } } -impl Encodable for SyntaxContext { +impl Encodable for ExpnId { fn encode<E: Encoder>(&self, _: &mut E) -> Result<(), E::Error> { Ok(()) // FIXME(jseyfried) intercrate hygiene } } -impl Decodable for SyntaxContext { - fn decode<D: Decoder>(_: &mut D) -> Result<SyntaxContext, D::Error> { - Ok(SyntaxContext::empty()) // FIXME(jseyfried) intercrate hygiene +impl Decodable for ExpnId { + fn decode<D: Decoder>(_: &mut D) -> Result<Self, D::Error> { + Ok(ExpnId::root()) // FIXME(jseyfried) intercrate hygiene } } diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index 02a7433d946..a17cd7625fb 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -21,7 +21,7 @@ use rustc_serialize::{Encodable, Decodable, Encoder, Decoder}; pub mod edition; use edition::Edition; pub mod hygiene; -pub use hygiene::{ExpnId, SyntaxContext, ExpnInfo, ExpnKind, MacroKind, DesugaringKind}; +pub use hygiene::{ExpnId, SyntaxContext, ExpnData, ExpnKind, MacroKind, DesugaringKind}; mod span_encoding; pub use span_encoding::{Span, DUMMY_SP}; @@ -49,7 +49,6 @@ pub struct Globals { symbol_interner: Lock<symbol::Interner>, span_interner: Lock<span_encoding::SpanInterner>, hygiene_data: Lock<hygiene::HygieneData>, - edition: Edition, } impl Globals { @@ -58,7 +57,6 @@ impl Globals { symbol_interner: Lock::new(symbol::Interner::fresh()), span_interner: Lock::new(span_encoding::SpanInterner::default()), hygiene_data: Lock::new(hygiene::HygieneData::new(edition)), - edition, } } } @@ -288,6 +286,17 @@ impl Span { span.lo.0 == 0 && span.hi.0 == 0 } + /// Returns `true` if this span comes from a macro or desugaring. + #[inline] + pub fn from_expansion(self) -> bool { + self.ctxt() != SyntaxContext::root() + } + + #[inline] + pub fn with_root_ctxt(lo: BytePos, hi: BytePos) -> Span { + Span::new(lo, hi, SyntaxContext::root()) + } + /// Returns a new span representing an empty span at the beginning of this span #[inline] pub fn shrink_to_lo(self) -> Span { @@ -344,20 +353,20 @@ impl Span { /// Returns the source span -- this is either the supplied span, or the span for /// the macro callsite that expanded to it. pub fn source_callsite(self) -> Span { - self.ctxt().outer_expn_info().map(|info| info.call_site.source_callsite()).unwrap_or(self) + let expn_data = self.ctxt().outer_expn_data(); + if !expn_data.is_root() { expn_data.call_site.source_callsite() } else { self } } /// The `Span` for the tokens in the previous macro expansion from which `self` was generated, /// if any. pub fn parent(self) -> Option<Span> { - self.ctxt().outer_expn_info().map(|i| i.call_site) + let expn_data = self.ctxt().outer_expn_data(); + if !expn_data.is_root() { Some(expn_data.call_site) } else { None } } /// Edition of the crate from which this span came. pub fn edition(self) -> edition::Edition { - self.ctxt().outer_expn_info().map_or_else(|| { - Edition::from_session() - }, |einfo| einfo.edition) + self.ctxt().outer_expn_data().edition } #[inline] @@ -373,52 +382,42 @@ impl Span { /// Returns the source callee. /// /// Returns `None` if the supplied span has no expansion trace, - /// else returns the `ExpnInfo` for the macro definition + /// else returns the `ExpnData` for the macro definition /// corresponding to the source callsite. - pub fn source_callee(self) -> Option<ExpnInfo> { - fn source_callee(info: ExpnInfo) -> ExpnInfo { - match info.call_site.ctxt().outer_expn_info() { - Some(info) => source_callee(info), - None => info, - } + pub fn source_callee(self) -> Option<ExpnData> { + fn source_callee(expn_data: ExpnData) -> ExpnData { + let next_expn_data = expn_data.call_site.ctxt().outer_expn_data(); + if !next_expn_data.is_root() { source_callee(next_expn_data) } else { expn_data } } - self.ctxt().outer_expn_info().map(source_callee) + let expn_data = self.ctxt().outer_expn_data(); + if !expn_data.is_root() { Some(source_callee(expn_data)) } else { None } } /// Checks if a span is "internal" to a macro in which `#[unstable]` /// items can be used (that is, a macro marked with /// `#[allow_internal_unstable]`). pub fn allows_unstable(&self, feature: Symbol) -> bool { - match self.ctxt().outer_expn_info() { - Some(info) => info - .allow_internal_unstable - .map_or(false, |features| features.iter().any(|&f| - f == feature || f == sym::allow_internal_unstable_backcompat_hack - )), - None => false, - } + self.ctxt().outer_expn_data().allow_internal_unstable.map_or(false, |features| { + features.iter().any(|&f| { + f == feature || f == sym::allow_internal_unstable_backcompat_hack + }) + }) } /// Checks if this span arises from a compiler desugaring of kind `kind`. pub fn is_desugaring(&self, kind: DesugaringKind) -> bool { - match self.ctxt().outer_expn_info() { - Some(info) => match info.kind { - ExpnKind::Desugaring(k) => k == kind, - _ => false, - }, - None => false, + match self.ctxt().outer_expn_data().kind { + ExpnKind::Desugaring(k) => k == kind, + _ => false, } } /// Returns the compiler desugaring that created this span, or `None` /// if this span is not from a desugaring. pub fn desugaring_kind(&self) -> Option<DesugaringKind> { - match self.ctxt().outer_expn_info() { - Some(info) => match info.kind { - ExpnKind::Desugaring(k) => Some(k), - _ => None - }, - None => None + match self.ctxt().outer_expn_data().kind { + ExpnKind::Desugaring(k) => Some(k), + _ => None } } @@ -426,19 +425,20 @@ impl Span { /// can be used without triggering the `unsafe_code` lint // (that is, a macro marked with `#[allow_internal_unsafe]`). pub fn allows_unsafe(&self) -> bool { - match self.ctxt().outer_expn_info() { - Some(info) => info.allow_internal_unsafe, - None => false, - } + self.ctxt().outer_expn_data().allow_internal_unsafe } pub fn macro_backtrace(mut self) -> Vec<MacroBacktrace> { let mut prev_span = DUMMY_SP; let mut result = vec![]; - while let Some(info) = self.ctxt().outer_expn_info() { + loop { + let expn_data = self.ctxt().outer_expn_data(); + if expn_data.is_root() { + break; + } // Don't print recursive invocations. - if !info.call_site.source_equal(&prev_span) { - let (pre, post) = match info.kind { + if !expn_data.call_site.source_equal(&prev_span) { + let (pre, post) = match expn_data.kind { ExpnKind::Root => break, ExpnKind::Desugaring(..) => ("desugaring of ", ""), ExpnKind::Macro(macro_kind, _) => match macro_kind { @@ -448,14 +448,14 @@ impl Span { } }; result.push(MacroBacktrace { - call_site: info.call_site, - macro_decl_name: format!("{}{}{}", pre, info.kind.descr(), post), - def_site_span: info.def_site, + call_site: expn_data.call_site, + macro_decl_name: format!("{}{}{}", pre, expn_data.kind.descr(), post), + def_site_span: expn_data.def_site, }); } prev_span = self; - self = info.call_site; + self = expn_data.call_site; } result } @@ -468,9 +468,9 @@ impl Span { // Return the macro span on its own to avoid weird diagnostic output. It is preferable to // have an incomplete span than a completely nonsensical one. if span_data.ctxt != end_data.ctxt { - if span_data.ctxt == SyntaxContext::empty() { + if span_data.ctxt == SyntaxContext::root() { return end; - } else if end_data.ctxt == SyntaxContext::empty() { + } else if end_data.ctxt == SyntaxContext::root() { return self; } // Both spans fall within a macro. @@ -479,7 +479,7 @@ impl Span { Span::new( cmp::min(span_data.lo, end_data.lo), cmp::max(span_data.hi, end_data.hi), - if span_data.ctxt == SyntaxContext::empty() { end_data.ctxt } else { span_data.ctxt }, + if span_data.ctxt == SyntaxContext::root() { end_data.ctxt } else { span_data.ctxt }, ) } @@ -490,7 +490,7 @@ impl Span { Span::new( span.hi, end.lo, - if end.ctxt == SyntaxContext::empty() { end.ctxt } else { span.ctxt }, + if end.ctxt == SyntaxContext::root() { end.ctxt } else { span.ctxt }, ) } @@ -501,7 +501,7 @@ impl Span { Span::new( span.lo, end.lo, - if end.ctxt == SyntaxContext::empty() { end.ctxt } else { span.ctxt }, + if end.ctxt == SyntaxContext::root() { end.ctxt } else { span.ctxt }, ) } @@ -611,7 +611,7 @@ impl rustc_serialize::UseSpecializedDecodable for Span { d.read_struct("Span", 2, |d| { let lo = d.read_struct_field("lo", 0, Decodable::decode)?; let hi = d.read_struct_field("hi", 1, Decodable::decode)?; - Ok(Span::new(lo, hi, NO_EXPANSION)) + Ok(Span::with_root_ctxt(lo, hi)) }) } } @@ -755,8 +755,6 @@ impl From<Vec<Span>> for MultiSpan { } } -pub const NO_EXPANSION: SyntaxContext = SyntaxContext::empty(); - /// Identifies an offset of a multi-byte character in a `SourceFile`. #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Eq, PartialEq, Debug)] pub struct MultiByteChar { @@ -1045,6 +1043,7 @@ impl SourceFile { mut src: String, start_pos: BytePos) -> Result<SourceFile, OffsetOverflowError> { remove_bom(&mut src); + normalize_newlines(&mut src); let src_hash = { let mut hasher: StableHasher<u128> = StableHasher::new(); @@ -1212,6 +1211,61 @@ fn remove_bom(src: &mut String) { } } + +/// Replaces `\r\n` with `\n` in-place in `src`. +/// +/// Returns error if there's a lone `\r` in the string +fn normalize_newlines(src: &mut String) { + if !src.as_bytes().contains(&b'\r') { + return; + } + + // We replace `\r\n` with `\n` in-place, which doesn't break utf-8 encoding. + // While we *can* call `as_mut_vec` and do surgery on the live string + // directly, let's rather steal the contents of `src`. This makes the code + // safe even if a panic occurs. + + let mut buf = std::mem::replace(src, String::new()).into_bytes(); + let mut gap_len = 0; + let mut tail = buf.as_mut_slice(); + loop { + let idx = match find_crlf(&tail[gap_len..]) { + None => tail.len(), + Some(idx) => idx + gap_len, + }; + tail.copy_within(gap_len..idx, 0); + tail = &mut tail[idx - gap_len..]; + if tail.len() == gap_len { + break; + } + gap_len += 1; + } + + // Account for removed `\r`. + // After `set_len`, `buf` is guaranteed to contain utf-8 again. + let new_len = buf.len() - gap_len; + unsafe { + buf.set_len(new_len); + *src = String::from_utf8_unchecked(buf); + } + + fn find_crlf(src: &[u8]) -> Option<usize> { + let mut search_idx = 0; + while let Some(idx) = find_cr(&src[search_idx..]) { + if src[search_idx..].get(idx + 1) != Some(&b'\n') { + search_idx += idx + 1; + continue; + } + return Some(search_idx + idx); + } + None + } + + fn find_cr(src: &[u8]) -> Option<usize> { + src.iter().position(|&b| b == b'\r') + } +} + // _____________________________________________________________________________ // Pos, BytePos, CharPos // diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 2d9556233d1..0b8f16bbc3b 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -8,13 +8,13 @@ use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::newtype_index; 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::fmt; use std::hash::{Hash, Hasher}; use std::str; -use crate::hygiene::SyntaxContext; use crate::{Span, DUMMY_SP, GLOBALS}; #[cfg(test)] @@ -470,6 +470,7 @@ symbols! { option_env, opt_out_copy, or, + or_patterns, Ord, Ordering, Output, @@ -610,7 +611,6 @@ symbols! { rust_eh_personality, rust_eh_unwind_resume, rust_oom, - __rust_unstable_column, rvalue_static_promotion, sanitizer_runtime, _Self, @@ -745,25 +745,25 @@ impl Ident { Ident { name, span } } - /// Constructs a new identifier with an empty syntax context. + /// Constructs a new identifier with a dummy span. #[inline] - pub const fn with_empty_ctxt(name: Symbol) -> Ident { + pub const fn with_dummy_span(name: Symbol) -> Ident { Ident::new(name, DUMMY_SP) } #[inline] pub fn invalid() -> Ident { - Ident::with_empty_ctxt(kw::Invalid) + 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_empty_ctxt(string.as_symbol()) + Ident::with_dummy_span(string.as_symbol()) } /// Maps a string to an identifier with an empty span. pub fn from_str(string: &str) -> Ident { - Ident::with_empty_ctxt(Symbol::intern(string)) + Ident::with_dummy_span(Symbol::intern(string)) } /// Maps a string and a span to an identifier. @@ -849,28 +849,9 @@ impl fmt::Display for Ident { } } -impl Encodable for Ident { - fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> { - if self.span.ctxt().modern() == SyntaxContext::empty() { - s.emit_str(&self.as_str()) - } else { // FIXME(jseyfried): intercrate hygiene - let mut string = "#".to_owned(); - string.push_str(&self.as_str()); - s.emit_str(&string) - } - } -} +impl UseSpecializedEncodable for Ident {} -impl Decodable for Ident { - fn decode<D: Decoder>(d: &mut D) -> Result<Ident, D::Error> { - let string = d.read_str()?; - Ok(if !string.starts_with('#') { - Ident::from_str(&string) - } else { // FIXME(jseyfried): intercrate hygiene - Ident::from_str(&string[1..]).gensym() - }) - } -} +impl UseSpecializedDecodable for Ident {} /// A symbol is an interned or gensymed string. A gensym is a symbol that is /// never equal to any other symbol. diff --git a/src/libsyntax_pos/tests.rs b/src/libsyntax_pos/tests.rs index 78c4e18e6ae..6bd6016020a 100644 --- a/src/libsyntax_pos/tests.rs +++ b/src/libsyntax_pos/tests.rs @@ -16,3 +16,23 @@ fn test_lookup_line() { assert_eq!(lookup_line(lines, BytePos(28)), 2); assert_eq!(lookup_line(lines, BytePos(29)), 2); } + +#[test] +fn test_normalize_newlines() { + fn check(before: &str, after: &str) { + let mut actual = before.to_string(); + normalize_newlines(&mut actual); + assert_eq!(actual.as_str(), after); + } + check("", ""); + check("\n", "\n"); + check("\r", "\r"); + check("\r\r", "\r\r"); + check("\r\n", "\n"); + check("hello world", "hello world"); + check("hello\nworld", "hello\nworld"); + check("hello\r\nworld", "hello\nworld"); + check("\r\nhello\r\nworld\r\n", "\nhello\nworld\n"); + check("\r\r\n", "\r\n"); + check("hello\rworld", "hello\rworld"); +} diff --git a/src/libunwind/Cargo.toml b/src/libunwind/Cargo.toml index f0f1bab425d..f10df8c85ba 100644 --- a/src/libunwind/Cargo.toml +++ b/src/libunwind/Cargo.toml @@ -22,7 +22,7 @@ compiler_builtins = "0.1.0" cfg-if = "0.1.8" [build-dependencies] -cc = { optional = true, version = "1.0.1" } +cc = { version = "1.0.1" } [features] -llvm-libunwind = ["cc"] +llvm-libunwind = [] diff --git a/src/libunwind/build.rs b/src/libunwind/build.rs index da31a49ddf2..f24d957d67b 100644 --- a/src/libunwind/build.rs +++ b/src/libunwind/build.rs @@ -4,17 +4,15 @@ fn main() { println!("cargo:rerun-if-changed=build.rs"); let target = env::var("TARGET").expect("TARGET was not set"); - // FIXME: the not(bootstrap) part is needed because of the issue addressed by #62286, - // and could be removed once that change is in beta. - if cfg!(all(not(bootstrap), feature = "llvm-libunwind")) && - (target.contains("linux") || + if cfg!(feature = "llvm-libunwind") && + ((target.contains("linux") && !target.contains("musl")) || target.contains("fuchsia")) { // Build the unwinding from libunwind C/C++ source code. - #[cfg(all(not(bootstrap), feature = "llvm-libunwind"))] llvm_libunwind::compile(); } else if target.contains("linux") { if target.contains("musl") { - // musl is handled in lib.rs + // linking for musl is handled in lib.rs + llvm_libunwind::compile(); } else if !target.contains("android") { println!("cargo:rustc-link-lib=gcc_s"); } @@ -25,7 +23,11 @@ fn main() { } else if target.contains("netbsd") { println!("cargo:rustc-link-lib=gcc_s"); } else if target.contains("openbsd") { - println!("cargo:rustc-link-lib=c++abi"); + if target.contains("sparc64") { + println!("cargo:rustc-link-lib=gcc"); + } else { + println!("cargo:rustc-link-lib=c++abi"); + } } else if target.contains("solaris") { println!("cargo:rustc-link-lib=gcc_s"); } else if target.contains("dragonfly") { @@ -46,7 +48,6 @@ fn main() { } } -#[cfg(all(not(bootstrap), feature = "llvm-libunwind"))] mod llvm_libunwind { use std::env; use std::path::Path; @@ -98,6 +99,15 @@ mod llvm_libunwind { cfg.file(root.join("src").join(src)); } + if target_env == "musl" { + // use the same C compiler command to compile C++ code so we do not need to setup the + // C++ compiler env variables on the builders + cfg.cpp(false); + // linking for musl is handled in lib.rs + cfg.cargo_metadata(false); + println!("cargo:rustc-link-search=native={}", env::var("OUT_DIR").unwrap()); + } + cfg.compile("unwind"); } } diff --git a/src/libunwind/libunwind.rs b/src/libunwind/libunwind.rs index aacbfc547d4..7c9eaa51fd9 100644 --- a/src/libunwind/libunwind.rs +++ b/src/libunwind/libunwind.rs @@ -70,7 +70,7 @@ pub enum _Unwind_Context {} pub type _Unwind_Exception_Cleanup_Fn = extern "C" fn(unwind_code: _Unwind_Reason_Code, exception: *mut _Unwind_Exception); -#[cfg_attr(all(not(bootstrap), feature = "llvm-libunwind", +#[cfg_attr(all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux")), link(name = "unwind", kind = "static"))] extern "C" { @@ -97,7 +97,7 @@ if #[cfg(all(any(target_os = "ios", target_os = "netbsd", not(target_arch = "arm } pub use _Unwind_Action::*; - #[cfg_attr(all(not(bootstrap), feature = "llvm-libunwind", + #[cfg_attr(all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux")), link(name = "unwind", kind = "static"))] extern "C" { @@ -153,7 +153,7 @@ if #[cfg(all(any(target_os = "ios", target_os = "netbsd", not(target_arch = "arm pub const UNWIND_POINTER_REG: c_int = 12; pub const UNWIND_IP_REG: c_int = 15; - #[cfg_attr(all(not(bootstrap), feature = "llvm-libunwind", + #[cfg_attr(all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux")), link(name = "unwind", kind = "static"))] extern "C" { @@ -218,7 +218,7 @@ if #[cfg(all(any(target_os = "ios", target_os = "netbsd", not(target_arch = "arm cfg_if::cfg_if! { if #[cfg(not(all(target_os = "ios", target_arch = "arm")))] { // Not 32-bit iOS - #[cfg_attr(all(not(bootstrap), feature = "llvm-libunwind", + #[cfg_attr(all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux")), link(name = "unwind", kind = "static"))] extern "C" { @@ -230,7 +230,7 @@ if #[cfg(not(all(target_os = "ios", target_arch = "arm")))] { } } else { // 32-bit iOS uses SjLj and does not provide _Unwind_Backtrace() - #[cfg_attr(all(not(bootstrap), feature = "llvm-libunwind", + #[cfg_attr(all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux")), link(name = "unwind", kind = "static"))] extern "C" { diff --git a/src/stage0.txt b/src/stage0.txt index 14d65bef8f6..1a9e64a1862 100644 --- a/src/stage0.txt +++ b/src/stage0.txt @@ -12,7 +12,7 @@ # source tarball for a stable release you'll likely see `1.x.0` for rustc and # `0.x.0` for Cargo where they were released on `date`. -date: 2019-07-04 +date: 2019-08-13 rustc: beta cargo: beta @@ -25,7 +25,7 @@ cargo: beta # # This means that there's a small window of time (a few days) where artifacts # are downloaded from dev-static.rust-lang.org instead of static.rust-lang.org. -# In order to ease this transition we have an extra key which is in the +# In order to ease this transition we have an extra key which is in the # configuration file below. When uncommented this will instruct the bootstrap.py # script to download from dev-static.rust-lang.org. # diff --git a/src/test/codegen/issue-45222.rs b/src/test/codegen/issue-45222.rs index 7f99ca724cf..7aadc8a0954 100644 --- a/src/test/codegen/issue-45222.rs +++ b/src/test/codegen/issue-45222.rs @@ -5,7 +5,6 @@ // verify that LLVM recognizes a loop involving 0..=n and will const-fold it. -//------------------------------------------------------------------------------ // Example from original issue #45222 fn foo2(n: u64) -> u64 { @@ -25,7 +24,6 @@ pub fn check_foo2() -> u64 { foo2(100000) } -//------------------------------------------------------------------------------ // Simplified example of #45222 fn triangle_inc(n: u64) -> u64 { @@ -43,7 +41,6 @@ pub fn check_triangle_inc() -> u64 { triangle_inc(100000) } -//------------------------------------------------------------------------------ // Demo in #48012 fn foo3r(n: u64) -> u64 { diff --git a/src/test/codegen/iter-fold-closure-no-dupes.rs b/src/test/codegen/iter-fold-closure-no-dupes.rs new file mode 100644 index 00000000000..ec58f7068ab --- /dev/null +++ b/src/test/codegen/iter-fold-closure-no-dupes.rs @@ -0,0 +1,14 @@ +//! Check that fold closures aren't duplicated for each iterator type. +// compile-flags: -C opt-level=0 + +fn main() { + (0i32..10).by_ref().count(); + (0i32..=10).by_ref().count(); +} + +// `count` calls `fold`, which calls `try_fold` -- find the `fold` closure: +// CHECK: {{^define.*Iterator::fold::.*closure}} +// +// Only one closure is needed for both `count` calls, even from different +// monomorphized iterator types, as it's only generic over the item type. +// CHECK-NOT: {{^define.*Iterator::fold::.*closure}} diff --git a/src/test/codegen/iter-fold-closure-no-iterator.rs b/src/test/codegen/iter-fold-closure-no-iterator.rs new file mode 100644 index 00000000000..fbeafd5f395 --- /dev/null +++ b/src/test/codegen/iter-fold-closure-no-iterator.rs @@ -0,0 +1,10 @@ +//! Check that fold closures aren't generic in the iterator type. +// compile-flags: -C opt-level=0 + +fn main() { + (0i32..10).by_ref().count(); +} + +// `count` calls `fold`, which calls `try_fold` -- that `fold` closure should +// not be generic in the iterator type, only in the item type. +// CHECK-NOT: {{^define.*Iterator::fold::.*closure.*Range}} diff --git a/src/test/incremental/hashes/call_expressions.rs b/src/test/incremental/hashes/call_expressions.rs index d859cbef39f..50d3657d417 100644 --- a/src/test/incremental/hashes/call_expressions.rs +++ b/src/test/incremental/hashes/call_expressions.rs @@ -18,7 +18,7 @@ fn callee1(_x: u32, _y: i64) {} fn callee2(_x: u32, _y: i64) {} -// Change Callee (Function) ---------------------------------------------------- +// Change Callee (Function) #[cfg(cfail1)] pub fn change_callee_function() { callee1(1, 2) @@ -33,7 +33,7 @@ pub fn change_callee_function() { -// Change Argument (Function) -------------------------------------------------- +// Change Argument (Function) #[cfg(cfail1)] pub fn change_argument_function() { callee1(1, 2) @@ -48,7 +48,7 @@ pub fn change_argument_function() { -// Change Callee Indirectly (Function) ----------------------------------------- +// Change Callee Indirectly (Function) mod change_callee_indirectly_function { #[cfg(cfail1)] use super::callee1 as callee; @@ -73,7 +73,7 @@ impl Struct { fn method2(&self, _x: char, _y: bool) {} } -// Change Callee (Method) ------------------------------------------------------ +// Change Callee (Method) #[cfg(cfail1)] pub fn change_callee_method() { let s = Struct; @@ -90,7 +90,7 @@ pub fn change_callee_method() { -// Change Argument (Method) ---------------------------------------------------- +// Change Argument (Method) #[cfg(cfail1)] pub fn change_argument_method() { let s = Struct; @@ -107,7 +107,7 @@ pub fn change_argument_method() { -// Change Callee (Method, UFCS) ------------------------------------------------ +// Change Callee (Method, UFCS) #[cfg(cfail1)] pub fn change_ufcs_callee_method() { let s = Struct; @@ -124,7 +124,7 @@ pub fn change_ufcs_callee_method() { -// Change Argument (Method, UFCS) ---------------------------------------------- +// Change Argument (Method, UFCS) #[cfg(cfail1)] pub fn change_argument_method_ufcs() { let s = Struct; @@ -141,7 +141,7 @@ pub fn change_argument_method_ufcs() { -// Change To UFCS -------------------------------------------------------------- +// Change To UFCS #[cfg(cfail1)] pub fn change_to_ufcs() { let s = Struct; @@ -164,7 +164,7 @@ impl Struct2 { fn method1(&self, _x: char, _y: bool) {} } -// Change UFCS Callee Indirectly ----------------------------------------------- +// Change UFCS Callee Indirectly pub mod change_ufcs_callee_indirectly { #[cfg(cfail1)] use super::Struct as Struct; diff --git a/src/test/incremental/hashes/closure_expressions.rs b/src/test/incremental/hashes/closure_expressions.rs index 24ab6b8e184..08693560d0b 100644 --- a/src/test/incremental/hashes/closure_expressions.rs +++ b/src/test/incremental/hashes/closure_expressions.rs @@ -14,7 +14,7 @@ #![crate_type="rlib"] -// Change closure body --------------------------------------------------------- +// Change closure body #[cfg(cfail1)] pub fn change_closure_body() { let _ = || 1u32; @@ -29,7 +29,7 @@ pub fn change_closure_body() { -// Add parameter --------------------------------------------------------------- +// Add parameter #[cfg(cfail1)] pub fn add_parameter() { let x = 0u32; @@ -46,7 +46,7 @@ pub fn add_parameter() { -// Change parameter pattern ---------------------------------------------------- +// Change parameter pattern #[cfg(cfail1)] pub fn change_parameter_pattern() { let _ = |x: (u32,)| x; @@ -61,7 +61,7 @@ pub fn change_parameter_pattern() { -// Add `move` to closure ------------------------------------------------------- +// Add `move` to closure #[cfg(cfail1)] pub fn add_move() { let _ = || 1; @@ -76,7 +76,7 @@ pub fn add_move() { -// Add type ascription to parameter -------------------------------------------- +// Add type ascription to parameter #[cfg(cfail1)] pub fn add_type_ascription_to_parameter() { let closure = |x| x + 1u32; @@ -93,7 +93,7 @@ pub fn add_type_ascription_to_parameter() { -// Change parameter type ------------------------------------------------------- +// Change parameter type #[cfg(cfail1)] pub fn change_parameter_type() { let closure = |x: u32| (x as u64) + 1; diff --git a/src/test/incremental/hashes/consts.rs b/src/test/incremental/hashes/consts.rs index 8e713a1d992..3d2eed89636 100644 --- a/src/test/incremental/hashes/consts.rs +++ b/src/test/incremental/hashes/consts.rs @@ -14,7 +14,7 @@ #![crate_type="rlib"] -// Change const visibility --------------------------------------------------- +// Change const visibility #[cfg(cfail1)] const CONST_VISIBILITY: u8 = 0; @@ -24,7 +24,7 @@ const CONST_VISIBILITY: u8 = 0; pub const CONST_VISIBILITY: u8 = 0; -// Change type from i32 to u32 ------------------------------------------------ +// Change type from i32 to u32 #[cfg(cfail1)] const CONST_CHANGE_TYPE_1: i32 = 0; @@ -34,7 +34,7 @@ const CONST_CHANGE_TYPE_1: i32 = 0; const CONST_CHANGE_TYPE_1: u32 = 0; -// Change type from Option<u32> to Option<u64> -------------------------------- +// Change type from Option<u32> to Option<u64> #[cfg(cfail1)] const CONST_CHANGE_TYPE_2: Option<u32> = None; @@ -44,7 +44,7 @@ const CONST_CHANGE_TYPE_2: Option<u32> = None; const CONST_CHANGE_TYPE_2: Option<u64> = None; -// Change value between simple literals --------------------------------------- +// Change value between simple literals #[rustc_clean(cfg="cfail2", except="HirBody")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_VALUE_1: i16 = { @@ -56,7 +56,7 @@ const CONST_CHANGE_VALUE_1: i16 = { }; -// Change value between expressions ------------------------------------------- +// Change value between expressions #[rustc_clean(cfg="cfail2", except="HirBody")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_VALUE_2: i16 = { @@ -88,7 +88,7 @@ const CONST_CHANGE_VALUE_4: i16 = { }; -// Change type indirectly ----------------------------------------------------- +// Change type indirectly struct ReferencedType1; struct ReferencedType2; diff --git a/src/test/incremental/hashes/if_expressions.rs b/src/test/incremental/hashes/if_expressions.rs index b84c393573b..4b73f1371f8 100644 --- a/src/test/incremental/hashes/if_expressions.rs +++ b/src/test/incremental/hashes/if_expressions.rs @@ -14,7 +14,7 @@ #![feature(rustc_attrs)] #![crate_type="rlib"] -// Change condition (if) ------------------------------------------------------- +// Change condition (if) #[cfg(cfail1)] pub fn change_condition(x: bool) -> u32 { if x { @@ -35,7 +35,7 @@ pub fn change_condition(x: bool) -> u32 { return 0 } -// Change then branch (if) ----------------------------------------------------- +// Change then branch (if) #[cfg(cfail1)] pub fn change_then_branch(x: bool) -> u32 { if x { @@ -58,7 +58,7 @@ pub fn change_then_branch(x: bool) -> u32 { -// Change else branch (if) ----------------------------------------------------- +// Change else branch (if) #[cfg(cfail1)] pub fn change_else_branch(x: bool) -> u32 { if x { @@ -81,7 +81,7 @@ pub fn change_else_branch(x: bool) -> u32 { -// Add else branch (if) -------------------------------------------------------- +// Add else branch (if) #[cfg(cfail1)] pub fn add_else_branch(x: bool) -> u32 { let mut ret = 1; @@ -109,7 +109,7 @@ pub fn add_else_branch(x: bool) -> u32 { -// Change condition (if let) --------------------------------------------------- +// Change condition (if let) #[cfg(cfail1)] pub fn change_condition_if_let(x: Option<u32>) -> u32 { if let Some(_x) = x { @@ -132,7 +132,7 @@ pub fn change_condition_if_let(x: Option<u32>) -> u32 { -// Change then branch (if let) ------------------------------------------------- +// Change then branch (if let) #[cfg(cfail1)] pub fn change_then_branch_if_let(x: Option<u32>) -> u32 { if let Some(x) = x { @@ -155,7 +155,7 @@ pub fn change_then_branch_if_let(x: Option<u32>) -> u32 { -// Change else branch (if let) ------------------------------------------------- +// Change else branch (if let) #[cfg(cfail1)] pub fn change_else_branch_if_let(x: Option<u32>) -> u32 { if let Some(x) = x { @@ -178,7 +178,7 @@ pub fn change_else_branch_if_let(x: Option<u32>) -> u32 { -// Add else branch (if let) ---------------------------------------------------- +// Add else branch (if let) #[cfg(cfail1)] pub fn add_else_branch_if_let(x: Option<u32>) -> u32 { let mut ret = 1; diff --git a/src/test/incremental/hashes/indexing_expressions.rs b/src/test/incremental/hashes/indexing_expressions.rs index 4d39ed68701..08cf19d7760 100644 --- a/src/test/incremental/hashes/indexing_expressions.rs +++ b/src/test/incremental/hashes/indexing_expressions.rs @@ -13,7 +13,7 @@ #![feature(rustc_attrs)] #![crate_type="rlib"] -// Change simple index --------------------------------------------------------- +// Change simple index #[cfg(cfail1)] fn change_simple_index(slice: &[u32]) -> u32 { slice[3] @@ -30,7 +30,7 @@ fn change_simple_index(slice: &[u32]) -> u32 { -// Change lower bound ---------------------------------------------------------- +// Change lower bound #[cfg(cfail1)] fn change_lower_bound(slice: &[u32]) -> &[u32] { &slice[3..5] @@ -47,7 +47,7 @@ fn change_lower_bound(slice: &[u32]) -> &[u32] { -// Change upper bound ---------------------------------------------------------- +// Change upper bound #[cfg(cfail1)] fn change_upper_bound(slice: &[u32]) -> &[u32] { &slice[3..5] @@ -64,7 +64,7 @@ fn change_upper_bound(slice: &[u32]) -> &[u32] { -// Add lower bound ------------------------------------------------------------- +// Add lower bound #[cfg(cfail1)] fn add_lower_bound(slice: &[u32]) -> &[u32] { &slice[..4] @@ -81,7 +81,7 @@ fn add_lower_bound(slice: &[u32]) -> &[u32] { -// Add upper bound ------------------------------------------------------------- +// Add upper bound #[cfg(cfail1)] fn add_upper_bound(slice: &[u32]) -> &[u32] { &slice[3..] @@ -98,7 +98,7 @@ fn add_upper_bound(slice: &[u32]) -> &[u32] { -// Change mutability ----------------------------------------------------------- +// Change mutability #[cfg(cfail1)] fn change_mutability(slice: &mut [u32]) -> u32 { (&mut slice[3..5])[0] @@ -115,7 +115,7 @@ fn change_mutability(slice: &mut [u32]) -> u32 { -// Exclusive to inclusive range ------------------------------------------------ +// Exclusive to inclusive range #[cfg(cfail1)] fn exclusive_to_inclusive_range(slice: &[u32]) -> &[u32] { &slice[3..7] diff --git a/src/test/incremental/hashes/inline_asm.rs b/src/test/incremental/hashes/inline_asm.rs index deb1c45a528..c50ee73d714 100644 --- a/src/test/incremental/hashes/inline_asm.rs +++ b/src/test/incremental/hashes/inline_asm.rs @@ -16,7 +16,7 @@ -// Change template ------------------------------------------------------------- +// Change template #[cfg(cfail1)] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_template(a: i32) -> i32 { @@ -51,7 +51,7 @@ pub fn change_template(a: i32) -> i32 { -// Change output ------------------------------------------------------------- +// Change output #[cfg(cfail1)] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_output(a: i32) -> i32 { @@ -88,7 +88,7 @@ pub fn change_output(a: i32) -> i32 { -// Change input ------------------------------------------------------------- +// Change input #[cfg(cfail1)] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_input(_a: i32, _b: i32) -> i32 { @@ -123,7 +123,7 @@ pub fn change_input(_a: i32, _b: i32) -> i32 { -// Change input constraint ----------------------------------------------------- +// Change input constraint #[cfg(cfail1)] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_input_constraint(_a: i32, _b: i32) -> i32 { @@ -158,7 +158,7 @@ pub fn change_input_constraint(_a: i32, _b: i32) -> i32 { -// Change clobber -------------------------------------------------------------- +// Change clobber #[cfg(cfail1)] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_clobber(_a: i32) -> i32 { @@ -193,7 +193,7 @@ pub fn change_clobber(_a: i32) -> i32 { -// Change options -------------------------------------------------------------- +// Change options #[cfg(cfail1)] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_options(_a: i32) -> i32 { diff --git a/src/test/incremental/hashes/loop_expressions.rs b/src/test/incremental/hashes/loop_expressions.rs index 6222d948c98..a2222db4c59 100644 --- a/src/test/incremental/hashes/loop_expressions.rs +++ b/src/test/incremental/hashes/loop_expressions.rs @@ -14,7 +14,7 @@ #![crate_type="rlib"] -// Change loop body ------------------------------------------------------------ +// Change loop body #[cfg(cfail1)] pub fn change_loop_body() { let mut _x = 0; @@ -37,7 +37,7 @@ pub fn change_loop_body() { -// Add break ------------------------------------------------------------------- +// Add break #[cfg(cfail1)] pub fn add_break() { let mut _x = 0; @@ -59,7 +59,7 @@ pub fn add_break() { -// Add loop label -------------------------------------------------------------- +// Add loop label #[cfg(cfail1)] pub fn add_loop_label() { let mut _x = 0; @@ -82,7 +82,7 @@ pub fn add_loop_label() { -// Add loop label to break ----------------------------------------------------- +// Add loop label to break #[cfg(cfail1)] pub fn add_loop_label_to_break() { let mut _x = 0; @@ -105,7 +105,7 @@ pub fn add_loop_label_to_break() { -// Change break label ---------------------------------------------------------- +// Change break label #[cfg(cfail1)] pub fn change_break_label() { let mut _x = 0; @@ -132,7 +132,7 @@ pub fn change_break_label() { -// Add loop label to continue -------------------------------------------------- +// Add loop label to continue #[cfg(cfail1)] pub fn add_loop_label_to_continue() { let mut _x = 0; @@ -155,7 +155,7 @@ pub fn add_loop_label_to_continue() { -// Change continue label ---------------------------------------------------------- +// Change continue label #[cfg(cfail1)] pub fn change_continue_label() { let mut _x = 0; @@ -182,7 +182,7 @@ pub fn change_continue_label() { -// Change continue to break ---------------------------------------------------- +// Change continue to break #[cfg(cfail1)] pub fn change_continue_to_break() { let mut _x = 0; diff --git a/src/test/incremental/hashes/panic_exprs.rs b/src/test/incremental/hashes/panic_exprs.rs index b370fcce8ef..70b0a5ab78c 100644 --- a/src/test/incremental/hashes/panic_exprs.rs +++ b/src/test/incremental/hashes/panic_exprs.rs @@ -17,7 +17,7 @@ #![crate_type="rlib"] -// Indexing expression --------------------------------------------------------- +// Indexing expression #[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn indexing(slice: &[u8]) -> u8 { @@ -32,7 +32,7 @@ pub fn indexing(slice: &[u8]) -> u8 { } -// Arithmetic overflow plus ---------------------------------------------------- +// Arithmetic overflow plus #[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn arithmetic_overflow_plus(val: i32) -> i32 { @@ -47,7 +47,7 @@ pub fn arithmetic_overflow_plus(val: i32) -> i32 { } -// Arithmetic overflow minus ---------------------------------------------------- +// Arithmetic overflow minus #[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn arithmetic_overflow_minus(val: i32) -> i32 { @@ -62,7 +62,7 @@ pub fn arithmetic_overflow_minus(val: i32) -> i32 { } -// Arithmetic overflow mult ---------------------------------------------------- +// Arithmetic overflow mult #[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn arithmetic_overflow_mult(val: i32) -> i32 { @@ -77,7 +77,7 @@ pub fn arithmetic_overflow_mult(val: i32) -> i32 { } -// Arithmetic overflow negation ------------------------------------------------ +// Arithmetic overflow negation #[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn arithmetic_overflow_negation(val: i32) -> i32 { @@ -92,7 +92,7 @@ pub fn arithmetic_overflow_negation(val: i32) -> i32 { } -// Division by zero ------------------------------------------------------------ +// Division by zero #[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn division_by_zero(val: i32) -> i32 { @@ -106,7 +106,7 @@ pub fn division_by_zero(val: i32) -> i32 { } } -// Division by zero ------------------------------------------------------------ +// Division by zero #[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn mod_by_zero(val: i32) -> i32 { @@ -121,7 +121,7 @@ pub fn mod_by_zero(val: i32) -> i32 { } -// shift left ------------------------------------------------------------------ +// shift left #[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn shift_left(val: i32, shift: usize) -> i32 { @@ -136,7 +136,7 @@ pub fn shift_left(val: i32, shift: usize) -> i32 { } -// shift right ------------------------------------------------------------------ +// shift right #[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn shift_right(val: i32, shift: usize) -> i32 { diff --git a/src/test/incremental/hashes/statics.rs b/src/test/incremental/hashes/statics.rs index 6f74e0fdbc0..d70ebb08b71 100644 --- a/src/test/incremental/hashes/statics.rs +++ b/src/test/incremental/hashes/statics.rs @@ -16,7 +16,7 @@ #![crate_type="rlib"] -// Change static visibility --------------------------------------------------- +// Change static visibility #[cfg(cfail1)] static STATIC_VISIBILITY: u8 = 0; @@ -26,7 +26,7 @@ static STATIC_VISIBILITY: u8 = 0; pub static STATIC_VISIBILITY: u8 = 0; -// Change static mutability --------------------------------------------------- +// Change static mutability #[cfg(cfail1)] static STATIC_MUTABILITY: u8 = 0; @@ -36,7 +36,7 @@ static STATIC_MUTABILITY: u8 = 0; static mut STATIC_MUTABILITY: u8 = 0; -// Add linkage attribute ------------------------------------------------------ +// Add linkage attribute #[cfg(cfail1)] static STATIC_LINKAGE: u8 = 0; @@ -47,7 +47,7 @@ static STATIC_LINKAGE: u8 = 0; static STATIC_LINKAGE: u8 = 0; -// Add no_mangle attribute ---------------------------------------------------- +// Add no_mangle attribute #[cfg(cfail1)] static STATIC_NO_MANGLE: u8 = 0; @@ -58,7 +58,7 @@ static STATIC_NO_MANGLE: u8 = 0; static STATIC_NO_MANGLE: u8 = 0; -// Add thread_local attribute ------------------------------------------------- +// Add thread_local attribute #[cfg(cfail1)] static STATIC_THREAD_LOCAL: u8 = 0; @@ -69,7 +69,7 @@ static STATIC_THREAD_LOCAL: u8 = 0; static STATIC_THREAD_LOCAL: u8 = 0; -// Change type from i16 to u64 ------------------------------------------------ +// Change type from i16 to u64 #[cfg(cfail1)] static STATIC_CHANGE_TYPE_1: i16 = 0; @@ -79,7 +79,7 @@ static STATIC_CHANGE_TYPE_1: i16 = 0; static STATIC_CHANGE_TYPE_1: u64 = 0; -// Change type from Option<i8> to Option<u16> --------------------------------- +// Change type from Option<i8> to Option<u16> #[cfg(cfail1)] static STATIC_CHANGE_TYPE_2: Option<i8> = None; @@ -89,7 +89,7 @@ static STATIC_CHANGE_TYPE_2: Option<i8> = None; static STATIC_CHANGE_TYPE_2: Option<u16> = None; -// Change value between simple literals --------------------------------------- +// Change value between simple literals #[rustc_clean(cfg="cfail2", except="HirBody")] #[rustc_clean(cfg="cfail3")] static STATIC_CHANGE_VALUE_1: i16 = { @@ -101,7 +101,7 @@ static STATIC_CHANGE_VALUE_1: i16 = { }; -// Change value between expressions ------------------------------------------- +// Change value between expressions #[rustc_clean(cfg="cfail2", except="HirBody")] #[rustc_clean(cfg="cfail3")] static STATIC_CHANGE_VALUE_2: i16 = { @@ -133,7 +133,7 @@ static STATIC_CHANGE_VALUE_4: i16 = { }; -// Change type indirectly ----------------------------------------------------- +// Change type indirectly struct ReferencedType1; struct ReferencedType2; diff --git a/src/test/incremental/hashes/struct_constructors.rs b/src/test/incremental/hashes/struct_constructors.rs index b708b99eabc..456d5e74751 100644 --- a/src/test/incremental/hashes/struct_constructors.rs +++ b/src/test/incremental/hashes/struct_constructors.rs @@ -20,7 +20,7 @@ pub struct RegularStruct { z: i16, } -// Change field value (regular struct) ----------------------------------------- +// Change field value (regular struct) #[cfg(cfail1)] pub fn change_field_value_regular_struct() -> RegularStruct { RegularStruct { @@ -43,7 +43,7 @@ pub fn change_field_value_regular_struct() -> RegularStruct { -// Change field order (regular struct) ----------------------------------------- +// Change field order (regular struct) #[cfg(cfail1)] pub fn change_field_order_regular_struct() -> RegularStruct { RegularStruct { @@ -66,7 +66,7 @@ pub fn change_field_order_regular_struct() -> RegularStruct { -// Add field (regular struct) -------------------------------------------------- +// Add field (regular struct) #[cfg(cfail1)] pub fn add_field_regular_struct() -> RegularStruct { let struct1 = RegularStruct { @@ -100,7 +100,7 @@ pub fn add_field_regular_struct() -> RegularStruct { -// Change field label (regular struct) ----------------------------------------- +// Change field label (regular struct) #[cfg(cfail1)] pub fn change_field_label_regular_struct() -> RegularStruct { let struct1 = RegularStruct { @@ -141,7 +141,7 @@ pub struct RegularStruct2 { z: i8, } -// Change constructor path (regular struct) ------------------------------------ +// Change constructor path (regular struct) #[cfg(cfail1)] pub fn change_constructor_path_regular_struct() { let _ = RegularStruct { @@ -164,7 +164,7 @@ pub fn change_constructor_path_regular_struct() { -// Change constructor path indirectly (regular struct) ------------------------- +// Change constructor path indirectly (regular struct) pub mod change_constructor_path_indirectly_regular_struct { #[cfg(cfail1)] use super::RegularStruct as Struct; @@ -189,7 +189,7 @@ pub mod change_constructor_path_indirectly_regular_struct { pub struct TupleStruct(i32, i64, i16); -// Change field value (tuple struct) ------------------------------------------- +// Change field value (tuple struct) #[cfg(cfail1)] pub fn change_field_value_tuple_struct() -> TupleStruct { TupleStruct(0, 1, 2) @@ -206,7 +206,7 @@ pub fn change_field_value_tuple_struct() -> TupleStruct { pub struct TupleStruct2(u16, u16, u16); -// Change constructor path (tuple struct) -------------------------------------- +// Change constructor path (tuple struct) #[cfg(cfail1)] pub fn change_constructor_path_tuple_struct() { let _ = TupleStruct(0, 1, 2); @@ -221,7 +221,7 @@ pub fn change_constructor_path_tuple_struct() { -// Change constructor path indirectly (tuple struct) --------------------------- +// Change constructor path indirectly (tuple struct) pub mod change_constructor_path_indirectly_tuple_struct { #[cfg(cfail1)] use super::TupleStruct as Struct; diff --git a/src/test/incremental/hashes/trait_defs.rs b/src/test/incremental/hashes/trait_defs.rs index 30b4e306820..81ff99533fc 100644 --- a/src/test/incremental/hashes/trait_defs.rs +++ b/src/test/incremental/hashes/trait_defs.rs @@ -21,7 +21,7 @@ #![feature(intrinsics)] -// Change trait visibility -------------------------------------------------------- +// Change trait visibility #[cfg(cfail1)] trait TraitVisibility { } @@ -32,7 +32,7 @@ pub trait TraitVisibility { } -// Change trait unsafety ---------------------------------------------------------- +// Change trait unsafety #[cfg(cfail1)] trait TraitUnsafety { } @@ -43,7 +43,7 @@ unsafe trait TraitUnsafety { } -// Add method --------------------------------------------------------------------- +// Add method #[cfg(cfail1)] trait TraitAddMethod { } @@ -57,7 +57,7 @@ pub trait TraitAddMethod { -// Change name of method ---------------------------------------------------------- +// Change name of method #[cfg(cfail1)] trait TraitChangeMethodName { fn method(); @@ -72,7 +72,7 @@ trait TraitChangeMethodName { -// Add return type to method ------------------------------------------------------ +// Add return type to method #[cfg(cfail1)] trait TraitAddReturnType { fn method(); @@ -89,7 +89,7 @@ trait TraitAddReturnType { -// Change return type of method --------------------------------------------------- +// Change return type of method #[cfg(cfail1)] trait TraitChangeReturnType { fn method() -> u32; @@ -106,7 +106,7 @@ trait TraitChangeReturnType { -// Add parameter to method -------------------------------------------------------- +// Add parameter to method #[cfg(cfail1)] trait TraitAddParameterToMethod { fn method(); @@ -123,7 +123,7 @@ trait TraitAddParameterToMethod { -// Change name of method parameter ------------------------------------------------ +// Change name of method parameter #[cfg(cfail1)] trait TraitChangeMethodParameterName { fn method(a: u32); @@ -148,7 +148,7 @@ trait TraitChangeMethodParameterName { -// Change type of method parameter (i32 => i64) ----------------------------------- +// Change type of method parameter (i32 => i64) #[cfg(cfail1)] trait TraitChangeMethodParameterType { fn method(a: i32); @@ -165,7 +165,7 @@ trait TraitChangeMethodParameterType { -// Change type of method parameter (&i32 => &mut i32) ----------------------------- +// Change type of method parameter (&i32 => &mut i32) #[cfg(cfail1)] trait TraitChangeMethodParameterTypeRef { fn method(a: &i32); @@ -182,7 +182,7 @@ trait TraitChangeMethodParameterTypeRef { -// Change order of method parameters ---------------------------------------------- +// Change order of method parameters #[cfg(cfail1)] trait TraitChangeMethodParametersOrder { fn method(a: i32, b: i64); @@ -199,7 +199,7 @@ trait TraitChangeMethodParametersOrder { -// Add default implementation to method ------------------------------------------- +// Add default implementation to method #[cfg(cfail1)] trait TraitAddMethodAutoImplementation { fn method(); @@ -216,7 +216,7 @@ trait TraitAddMethodAutoImplementation { -// Change order of methods -------------------------------------------------------- +// Change order of methods #[cfg(cfail1)] trait TraitChangeOrderOfMethods { fn method0(); @@ -233,7 +233,7 @@ trait TraitChangeOrderOfMethods { -// Change mode of self parameter -------------------------------------------------- +// Change mode of self parameter #[cfg(cfail1)] trait TraitChangeModeSelfRefToMut { fn method(&self); @@ -284,7 +284,7 @@ trait TraitChangeModeSelfOwnToRef { -// Add unsafe modifier to method -------------------------------------------------- +// Add unsafe modifier to method #[cfg(cfail1)] trait TraitAddUnsafeModifier { fn method(); @@ -301,7 +301,7 @@ trait TraitAddUnsafeModifier { -// Add extern modifier to method -------------------------------------------------- +// Add extern modifier to method #[cfg(cfail1)] trait TraitAddExternModifier { fn method(); @@ -318,7 +318,7 @@ trait TraitAddExternModifier { -// Change extern "C" to extern "rust-intrinsic" ----------------------------------- +// Change extern "C" to extern "rust-intrinsic" #[cfg(cfail1)] trait TraitChangeExternCToRustIntrinsic { extern "C" fn method(); @@ -335,7 +335,7 @@ trait TraitChangeExternCToRustIntrinsic { -// Add type parameter to method --------------------------------------------------- +// Add type parameter to method #[cfg(cfail1)] trait TraitAddTypeParameterToMethod { fn method(); @@ -352,7 +352,7 @@ trait TraitAddTypeParameterToMethod { -// Add lifetime parameter to method ----------------------------------------------- +// Add lifetime parameter to method #[cfg(cfail1)] trait TraitAddLifetimeParameterToMethod { fn method(); @@ -373,7 +373,7 @@ trait TraitAddLifetimeParameterToMethod { trait ReferencedTrait0 { } trait ReferencedTrait1 { } -// Add trait bound to method type parameter --------------------------------------- +// Add trait bound to method type parameter #[cfg(cfail1)] trait TraitAddTraitBoundToMethodTypeParameter { fn method<T>(); @@ -390,7 +390,7 @@ trait TraitAddTraitBoundToMethodTypeParameter { -// Add builtin bound to method type parameter ------------------------------------- +// Add builtin bound to method type parameter #[cfg(cfail1)] trait TraitAddBuiltinBoundToMethodTypeParameter { fn method<T>(); @@ -407,7 +407,7 @@ trait TraitAddBuiltinBoundToMethodTypeParameter { -// Add lifetime bound to method lifetime parameter ------------------------------------ +// Add lifetime bound to method lifetime parameter #[cfg(cfail1)] trait TraitAddLifetimeBoundToMethodLifetimeParameter { fn method<'a, 'b>(a: &'a u32, b: &'b u32); @@ -424,7 +424,7 @@ trait TraitAddLifetimeBoundToMethodLifetimeParameter { -// Add second trait bound to method type parameter -------------------------------- +// Add second trait bound to method type parameter #[cfg(cfail1)] trait TraitAddSecondTraitBoundToMethodTypeParameter { fn method<T: ReferencedTrait0>(); @@ -441,7 +441,7 @@ trait TraitAddSecondTraitBoundToMethodTypeParameter { -// Add second builtin bound to method type parameter ------------------------------ +// Add second builtin bound to method type parameter #[cfg(cfail1)] trait TraitAddSecondBuiltinBoundToMethodTypeParameter { fn method<T: Sized>(); @@ -458,7 +458,7 @@ trait TraitAddSecondBuiltinBoundToMethodTypeParameter { -// Add second lifetime bound to method lifetime parameter ----------------------------- +// Add second lifetime bound to method lifetime parameter #[cfg(cfail1)] trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter { fn method<'a, 'b, 'c: 'a>(a: &'a u32, b: &'b u32, c: &'c u32); @@ -475,7 +475,7 @@ trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter { -// Add associated type ------------------------------------------------------------ +// Add associated type #[cfg(cfail1)] trait TraitAddAssociatedType { @@ -495,7 +495,7 @@ trait TraitAddAssociatedType { -// Add trait bound to associated type --------------------------------------------- +// Add trait bound to associated type #[cfg(cfail1)] trait TraitAddTraitBoundToAssociatedType { type Associated; @@ -519,7 +519,7 @@ trait TraitAddTraitBoundToAssociatedType { -// Add lifetime bound to associated type ------------------------------------------ +// Add lifetime bound to associated type #[cfg(cfail1)] trait TraitAddLifetimeBoundToAssociatedType<'a> { type Associated; @@ -540,7 +540,7 @@ trait TraitAddLifetimeBoundToAssociatedType<'a> { -// Add default to associated type ------------------------------------------------- +// Add default to associated type #[cfg(cfail1)] trait TraitAddDefaultToAssociatedType { type Associated; @@ -561,7 +561,7 @@ trait TraitAddDefaultToAssociatedType { -// Add associated constant -------------------------------------------------------- +// Add associated constant #[cfg(cfail1)] trait TraitAddAssociatedConstant { fn method(); @@ -578,7 +578,7 @@ trait TraitAddAssociatedConstant { -// Add initializer to associated constant ----------------------------------------- +// Add initializer to associated constant #[cfg(cfail1)] trait TraitAddInitializerToAssociatedConstant { const Value: u32; @@ -601,7 +601,7 @@ trait TraitAddInitializerToAssociatedConstant { -// Change type of associated constant --------------------------------------------- +// Change type of associated constant #[cfg(cfail1)] trait TraitChangeTypeOfAssociatedConstant { const Value: u32; @@ -624,7 +624,7 @@ trait TraitChangeTypeOfAssociatedConstant { -// Add super trait ---------------------------------------------------------------- +// Add super trait #[cfg(cfail1)] trait TraitAddSuperTrait { } @@ -635,7 +635,7 @@ trait TraitAddSuperTrait : ReferencedTrait0 { } -// Add builtin bound (Send or Copy) ----------------------------------------------- +// Add builtin bound (Send or Copy) #[cfg(cfail1)] trait TraitAddBuiltiBound { } @@ -646,7 +646,7 @@ trait TraitAddBuiltiBound : Send { } -// Add 'static lifetime bound to trait -------------------------------------------- +// Add 'static lifetime bound to trait #[cfg(cfail1)] trait TraitAddStaticLifetimeBound { } @@ -657,7 +657,7 @@ trait TraitAddStaticLifetimeBound : 'static { } -// Add super trait as second bound ------------------------------------------------ +// Add super trait as second bound #[cfg(cfail1)] trait TraitAddTraitAsSecondBound : ReferencedTrait0 { } @@ -676,7 +676,7 @@ trait TraitAddTraitAsSecondBoundFromBuiltin : Send + ReferencedTrait0 { } -// Add builtin bound as second bound ---------------------------------------------- +// Add builtin bound as second bound #[cfg(cfail1)] trait TraitAddBuiltinBoundAsSecondBound : ReferencedTrait0 { } @@ -695,7 +695,7 @@ trait TraitAddBuiltinBoundAsSecondBoundFromBuiltin: Send + Copy { } -// Add 'static bounds as second bound --------------------------------------------- +// Add 'static bounds as second bound #[cfg(cfail1)] trait TraitAddStaticBoundAsSecondBound : ReferencedTrait0 { } @@ -714,7 +714,7 @@ trait TraitAddStaticBoundAsSecondBoundFromBuiltin : Send + 'static { } -// Add type parameter to trait ---------------------------------------------------- +// Add type parameter to trait #[cfg(cfail1)] trait TraitAddTypeParameterToTrait { } @@ -725,7 +725,7 @@ trait TraitAddTypeParameterToTrait<T> { } -// Add lifetime parameter to trait ------------------------------------------------ +// Add lifetime parameter to trait #[cfg(cfail1)] trait TraitAddLifetimeParameterToTrait { } @@ -736,7 +736,7 @@ trait TraitAddLifetimeParameterToTrait<'a> { } -// Add trait bound to type parameter of trait ------------------------------------- +// Add trait bound to type parameter of trait #[cfg(cfail1)] trait TraitAddTraitBoundToTypeParameterOfTrait<T> { } @@ -747,7 +747,7 @@ trait TraitAddTraitBoundToTypeParameterOfTrait<T: ReferencedTrait0> { } -// Add lifetime bound to type parameter of trait ---------------------------------- +// Add lifetime bound to type parameter of trait #[cfg(cfail1)] trait TraitAddLifetimeBoundToTypeParameterOfTrait<'a, T> { } @@ -758,7 +758,7 @@ trait TraitAddLifetimeBoundToTypeParameterOfTrait<'a, T: 'a> { } -// Add lifetime bound to lifetime parameter of trait ------------------------------ +// Add lifetime bound to lifetime parameter of trait #[cfg(cfail1)] trait TraitAddLifetimeBoundToLifetimeParameterOfTrait<'a, 'b> { } @@ -769,7 +769,7 @@ trait TraitAddLifetimeBoundToLifetimeParameterOfTrait<'a: 'b, 'b> { } -// Add builtin bound to type parameter of trait ----------------------------------- +// Add builtin bound to type parameter of trait #[cfg(cfail1)] trait TraitAddBuiltinBoundToTypeParameterOfTrait<T> { } @@ -780,7 +780,7 @@ trait TraitAddBuiltinBoundToTypeParameterOfTrait<T: Send> { } -// Add second type parameter to trait --------------------------------------------- +// Add second type parameter to trait #[cfg(cfail1)] trait TraitAddSecondTypeParameterToTrait<T> { } @@ -791,7 +791,7 @@ trait TraitAddSecondTypeParameterToTrait<T, S> { } -// Add second lifetime parameter to trait ----------------------------------------- +// Add second lifetime parameter to trait #[cfg(cfail1)] trait TraitAddSecondLifetimeParameterToTrait<'a> { } @@ -802,7 +802,7 @@ trait TraitAddSecondLifetimeParameterToTrait<'a, 'b> { } -// Add second trait bound to type parameter of trait ------------------------------ +// Add second trait bound to type parameter of trait #[cfg(cfail1)] trait TraitAddSecondTraitBoundToTypeParameterOfTrait<T: ReferencedTrait0> { } @@ -813,7 +813,7 @@ trait TraitAddSecondTraitBoundToTypeParameterOfTrait<T: ReferencedTrait0 + Refer -// Add second lifetime bound to type parameter of trait --------------------------- +// Add second lifetime bound to type parameter of trait #[cfg(cfail1)] trait TraitAddSecondLifetimeBoundToTypeParameterOfTrait<'a, 'b, T: 'a> { } @@ -824,7 +824,7 @@ trait TraitAddSecondLifetimeBoundToTypeParameterOfTrait<'a, 'b, T: 'a + 'b> { } -// Add second lifetime bound to lifetime parameter of trait------------------------ +// Add second lifetime bound to lifetime parameter of trait #[cfg(cfail1)] trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTrait<'a: 'b, 'b, 'c> { } @@ -835,7 +835,7 @@ trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTrait<'a: 'b + 'c, 'b, 'c> -// Add second builtin bound to type parameter of trait ---------------------------- +// Add second builtin bound to type parameter of trait #[cfg(cfail1)] trait TraitAddSecondBuiltinBoundToTypeParameterOfTrait<T: Send> { } @@ -846,13 +846,12 @@ trait TraitAddSecondBuiltinBoundToTypeParameterOfTrait<T: Send + Sync> { } -// -------------------------------------------------------------------------------- struct ReferenceType0 {} struct ReferenceType1 {} -// Add trait bound to type parameter of trait in where clause---------------------- +// Add trait bound to type parameter of trait in where clause #[cfg(cfail1)] trait TraitAddTraitBoundToTypeParameterOfTraitWhere<T> { } @@ -863,7 +862,7 @@ trait TraitAddTraitBoundToTypeParameterOfTraitWhere<T> where T: ReferencedTrait0 -// Add lifetime bound to type parameter of trait in where clause------------------- +// Add lifetime bound to type parameter of trait in where clause #[cfg(cfail1)] trait TraitAddLifetimeBoundToTypeParameterOfTraitWhere<'a, T> { } @@ -874,7 +873,7 @@ trait TraitAddLifetimeBoundToTypeParameterOfTraitWhere<'a, T> where T: 'a { } -// Add lifetime bound to lifetime parameter of trait in where clause--------------- +// Add lifetime bound to lifetime parameter of trait in where clause #[cfg(cfail1)] trait TraitAddLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b> { } @@ -885,7 +884,7 @@ trait TraitAddLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b> where 'a: 'b -// Add builtin bound to type parameter of trait in where clause-------------------- +// Add builtin bound to type parameter of trait in where clause #[cfg(cfail1)] trait TraitAddBuiltinBoundToTypeParameterOfTraitWhere<T> { } @@ -896,7 +895,7 @@ trait TraitAddBuiltinBoundToTypeParameterOfTraitWhere<T> where T: Send { } -// Add second trait bound to type parameter of trait in where clause--------------- +// Add second trait bound to type parameter of trait in where clause #[cfg(cfail1)] trait TraitAddSecondTraitBoundToTypeParameterOfTraitWhere<T> where T: ReferencedTrait0 { } @@ -908,7 +907,7 @@ trait TraitAddSecondTraitBoundToTypeParameterOfTraitWhere<T> -// Add second lifetime bound to type parameter of trait in where clause------------ +// Add second lifetime bound to type parameter of trait in where clause #[cfg(cfail1)] trait TraitAddSecondLifetimeBoundToTypeParameterOfTraitWhere<'a, 'b, T> where T: 'a { } @@ -919,7 +918,7 @@ trait TraitAddSecondLifetimeBoundToTypeParameterOfTraitWhere<'a, 'b, T> where T: -// Add second lifetime bound to lifetime parameter of trait in where clause-------- +// Add second lifetime bound to lifetime parameter of trait in where clause #[cfg(cfail1)] trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b, 'c> where 'a: 'b { } @@ -930,7 +929,7 @@ trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b, 'c> whe -// Add second builtin bound to type parameter of trait in where clause------------- +// Add second builtin bound to type parameter of trait in where clause #[cfg(cfail1)] trait TraitAddSecondBuiltinBoundToTypeParameterOfTraitWhere<T> where T: Send { } @@ -940,7 +939,7 @@ trait TraitAddSecondBuiltinBoundToTypeParameterOfTraitWhere<T> where T: Send { } trait TraitAddSecondBuiltinBoundToTypeParameterOfTraitWhere<T> where T: Send + Sync { } -// Change return type of method indirectly by modifying a use statement------------ +// Change return type of method indirectly by modifying a use statement mod change_return_type_of_method_indirectly_use { #[cfg(cfail1)] use super::ReferenceType0 as ReturnType; @@ -958,7 +957,7 @@ mod change_return_type_of_method_indirectly_use { -// Change type of method parameter indirectly by modifying a use statement--------- +// Change type of method parameter indirectly by modifying a use statement mod change_method_parameter_type_indirectly_by_use { #[cfg(cfail1)] use super::ReferenceType0 as ArgType; diff --git a/src/test/incremental/hashes/while_let_loops.rs b/src/test/incremental/hashes/while_let_loops.rs index 39b28ec1906..da3c957741f 100644 --- a/src/test/incremental/hashes/while_let_loops.rs +++ b/src/test/incremental/hashes/while_let_loops.rs @@ -14,7 +14,7 @@ #![crate_type="rlib"] -// Change loop body ------------------------------------------------------------ +// Change loop body #[cfg(cfail1)] pub fn change_loop_body() { let mut _x = 0; @@ -37,7 +37,7 @@ pub fn change_loop_body() { -// Change loop body ------------------------------------------------------------ +// Change loop body #[cfg(cfail1)] pub fn change_loop_condition() { let mut _x = 0; @@ -60,7 +60,7 @@ pub fn change_loop_condition() { -// Add break ------------------------------------------------------------------- +// Add break #[cfg(cfail1)] pub fn add_break() { let mut _x = 0; @@ -82,7 +82,7 @@ pub fn add_break() { -// Add loop label -------------------------------------------------------------- +// Add loop label #[cfg(cfail1)] pub fn add_loop_label() { let mut _x = 0; @@ -105,7 +105,7 @@ pub fn add_loop_label() { -// Add loop label to break ----------------------------------------------------- +// Add loop label to break #[cfg(cfail1)] pub fn add_loop_label_to_break() { let mut _x = 0; @@ -128,7 +128,7 @@ pub fn add_loop_label_to_break() { -// Change break label ---------------------------------------------------------- +// Change break label #[cfg(cfail1)] pub fn change_break_label() { let mut _x = 0; @@ -155,7 +155,7 @@ pub fn change_break_label() { -// Add loop label to continue -------------------------------------------------- +// Add loop label to continue #[cfg(cfail1)] pub fn add_loop_label_to_continue() { let mut _x = 0; @@ -178,7 +178,7 @@ pub fn add_loop_label_to_continue() { -// Change continue label ---------------------------------------------------------- +// Change continue label #[cfg(cfail1)] pub fn change_continue_label() { let mut _x = 0; @@ -205,7 +205,7 @@ pub fn change_continue_label() { -// Change continue to break ---------------------------------------------------- +// Change continue to break #[cfg(cfail1)] pub fn change_continue_to_break() { let mut _x = 0; diff --git a/src/test/incremental/hashes/while_loops.rs b/src/test/incremental/hashes/while_loops.rs index 06072185469..3be42e7a4ee 100644 --- a/src/test/incremental/hashes/while_loops.rs +++ b/src/test/incremental/hashes/while_loops.rs @@ -14,7 +14,7 @@ #![crate_type="rlib"] -// Change loop body ------------------------------------------------------------ +// Change loop body #[cfg(cfail1)] pub fn change_loop_body() { let mut _x = 0; @@ -37,7 +37,7 @@ pub fn change_loop_body() { -// Change loop body ------------------------------------------------------------ +// Change loop body #[cfg(cfail1)] pub fn change_loop_condition() { let mut _x = 0; @@ -60,7 +60,7 @@ pub fn change_loop_condition() { -// Add break ------------------------------------------------------------------- +// Add break #[cfg(cfail1)] pub fn add_break() { let mut _x = 0; @@ -82,7 +82,7 @@ pub fn add_break() { -// Add loop label -------------------------------------------------------------- +// Add loop label #[cfg(cfail1)] pub fn add_loop_label() { let mut _x = 0; @@ -105,7 +105,7 @@ pub fn add_loop_label() { -// Add loop label to break ----------------------------------------------------- +// Add loop label to break #[cfg(cfail1)] pub fn add_loop_label_to_break() { let mut _x = 0; @@ -128,7 +128,7 @@ pub fn add_loop_label_to_break() { -// Change break label ---------------------------------------------------------- +// Change break label #[cfg(cfail1)] pub fn change_break_label() { let mut _x = 0; @@ -155,7 +155,7 @@ pub fn change_break_label() { -// Add loop label to continue -------------------------------------------------- +// Add loop label to continue #[cfg(cfail1)] pub fn add_loop_label_to_continue() { let mut _x = 0; @@ -178,7 +178,7 @@ pub fn add_loop_label_to_continue() { -// Change continue label ---------------------------------------------------------- +// Change continue label #[cfg(cfail1)] pub fn change_continue_label() { let mut _x = 0; @@ -205,7 +205,7 @@ pub fn change_continue_label() { -// Change continue to break ---------------------------------------------------- +// Change continue to break #[cfg(cfail1)] pub fn change_continue_to_break() { let mut _x = 0; diff --git a/src/test/mir-opt/retag.rs b/src/test/mir-opt/retag.rs index 33ee0fe61b2..db36a1fab5f 100644 --- a/src/test/mir-opt/retag.rs +++ b/src/test/mir-opt/retag.rs @@ -1,3 +1,4 @@ +// ignore-wasm32-bare compiled with panic=abort by default // ignore-tidy-linelength // compile-flags: -Z mir-emit-retag -Z mir-opt-level=0 -Z span_free_formats @@ -11,6 +12,10 @@ impl Test { fn foo_shr<'x>(&self, x: &'x i32) -> &'x i32 { x } } +impl Drop for Test { + fn drop(&mut self) {} +} + fn main() { let mut x = 0; { @@ -60,10 +65,12 @@ fn main() { // ... // bb0: { // ... -// _3 = const Test::foo(move _4, move _6) -> bb1; +// _3 = const Test::foo(move _4, move _6) -> [return: bb2, unwind: bb3]; // } // -// bb1: { +// ... +// +// bb2: { // Retag(_3); // ... // _9 = move _3; @@ -80,25 +87,20 @@ fn main() { // _12 = move _13 as *mut i32 (Misc); // Retag([raw] _12); // ... -// _16 = move _17(move _18) -> bb2; +// _16 = move _17(move _18) -> bb5; // } // -// bb2: { +// bb5: { // Retag(_16); // ... -// _20 = const Test::foo_shr(move _21, move _23) -> bb3; -// } -// -// bb3: { -// ... -// return; +// _20 = const Test::foo_shr(move _21, move _23) -> [return: bb6, unwind: bb7]; // } // // ... // } // END rustc.main.EraseRegions.after.mir // START rustc.main-{{closure}}.EraseRegions.after.mir -// fn main::{{closure}}#0(_1: &[closure@HirId { owner: DefIndex(20), local_id: 72 }], _2: &i32) -> &i32 { +// fn main::{{closure}}#0(_1: &[closure@HirId { owner: DefIndex(22), local_id: 72 }], _2: &i32) -> &i32 { // ... // bb0: { // Retag([fn entry] _1); @@ -113,3 +115,17 @@ fn main() { // } // } // END rustc.main-{{closure}}.EraseRegions.after.mir +// START rustc.ptr-real_drop_in_place.Test.SimplifyCfg-make_shim.after.mir +// fn std::ptr::real_drop_in_place(_1: &mut Test) -> () { +// ... +// bb0: { +// Retag([raw] _1); +// _2 = &mut (*_1); +// _3 = const <Test as std::ops::Drop>::drop(move _2) -> bb1; +// } +// +// bb1: { +// return; +// } +// } +// END rustc.ptr-real_drop_in_place.Test.SimplifyCfg-make_shim.after.mir diff --git a/src/test/pretty/stmt_expr_attributes.rs b/src/test/pretty/stmt_expr_attributes.rs index 02d93238dd6..619cce685d7 100644 --- a/src/test/pretty/stmt_expr_attributes.rs +++ b/src/test/pretty/stmt_expr_attributes.rs @@ -259,8 +259,6 @@ fn _12() { } } -///////////////// - fn foo() { } fn foo3(_: i32, _: (), _: ()) { } fn qux(_: i32) { } diff --git a/src/test/run-make-fulldeps/reproducible-build-2/Makefile b/src/test/run-make-fulldeps/reproducible-build-2/Makefile index b96954fea0d..45c9a742723 100644 --- a/src/test/run-make-fulldeps/reproducible-build-2/Makefile +++ b/src/test/run-make-fulldeps/reproducible-build-2/Makefile @@ -5,7 +5,8 @@ # Objects are reproducible but their path is not. all: \ - fat_lto + fat_lto \ + sysroot fat_lto: rm -rf $(TMPDIR) && mkdir $(TMPDIR) @@ -14,3 +15,12 @@ fat_lto: cp $(TMPDIR)/reproducible-build $(TMPDIR)/reproducible-build-a $(RUSTC) reproducible-build.rs -C lto=fat cmp "$(TMPDIR)/reproducible-build-a" "$(TMPDIR)/reproducible-build" || exit 1 + +sysroot: + rm -rf $(TMPDIR) && mkdir $(TMPDIR) + $(RUSTC) reproducible-build-aux.rs + $(RUSTC) reproducible-build.rs --crate-type rlib --sysroot $(shell $(RUSTC) --print sysroot) --remap-path-prefix=$(shell $(RUSTC) --print sysroot)=/sysroot + cp -r $(shell $(RUSTC) --print sysroot) $(TMPDIR)/sysroot + cp $(TMPDIR)/libreproducible_build.rlib $(TMPDIR)/libfoo.rlib + $(RUSTC) reproducible-build.rs --crate-type rlib --sysroot $(TMPDIR)/sysroot --remap-path-prefix=$(TMPDIR)/sysroot=/sysroot + cmp "$(TMPDIR)/libreproducible_build.rlib" "$(TMPDIR)/libfoo.rlib" || exit 1 diff --git a/src/test/rustdoc/async-fn.rs b/src/test/rustdoc/async-fn.rs index 7384f7027d1..5f9708a3972 100644 --- a/src/test/rustdoc/async-fn.rs +++ b/src/test/rustdoc/async-fn.rs @@ -1,7 +1,5 @@ // edition:2018 -#![feature(async_await)] - // @has async_fn/fn.foo.html '//pre[@class="rust fn"]' 'pub async fn foo() -> Option<Foo>' pub async fn foo() -> Option<Foo> { None diff --git a/src/test/rustdoc/async-move-doctest.rs b/src/test/rustdoc/async-move-doctest.rs index 42723132782..2ba61388c9e 100644 --- a/src/test/rustdoc/async-move-doctest.rs +++ b/src/test/rustdoc/async-move-doctest.rs @@ -1,13 +1,11 @@ // compile-flags:--test // edition:2018 -// prior to setting the default edition for the doctest pre-parser, this doctest would fail due to -// a fatal parsing error +// Prior to setting the default edition for the doctest pre-parser, +// this doctest would fail due to a fatal parsing error. // see https://github.com/rust-lang/rust/issues/59313 //! ``` -//! #![feature(async_await)] -//! //! fn foo() { //! drop(async move {}); //! } diff --git a/src/test/rustdoc/edition-flag.rs b/src/test/rustdoc/edition-flag.rs index 5571245f28d..ddbc2be651d 100644 --- a/src/test/rustdoc/edition-flag.rs +++ b/src/test/rustdoc/edition-flag.rs @@ -1,10 +1,7 @@ // compile-flags:--test -Z unstable-options // edition:2018 -#![feature(async_await)] - /// ```rust -/// #![feature(async_await)] /// fn main() { /// let _ = async { }; /// } diff --git a/src/test/ui-fulldeps/auxiliary/attr-plugin-test.rs b/src/test/ui-fulldeps/auxiliary/attr-plugin-test.rs index c2685c7f74c..c053c715248 100644 --- a/src/test/ui-fulldeps/auxiliary/attr-plugin-test.rs +++ b/src/test/ui-fulldeps/auxiliary/attr-plugin-test.rs @@ -4,10 +4,9 @@ #![feature(rustc_private)] extern crate rustc_driver; -extern crate rustc_plugin; extern crate syntax; -use rustc_plugin::Registry; +use rustc_driver::plugin::Registry; use syntax::ext::base::SyntaxExtension; use syntax::feature_gate::AttributeType; use syntax::symbol::Symbol; diff --git a/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs b/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs index ad42ee1d1ec..6fb99b2c983 100644 --- a/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs +++ b/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs @@ -3,11 +3,10 @@ #[macro_use] extern crate rustc; -extern crate rustc_plugin; extern crate rustc_driver; extern crate syntax; -use rustc_plugin::Registry; +use rustc_driver::plugin::Registry; use syntax::attr; use syntax::ext::base::*; use syntax::feature_gate::AttributeType::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 2826ae75bee..17386d7e1aa 100644 --- a/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs +++ b/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs @@ -4,12 +4,11 @@ #![feature(box_syntax)] #[macro_use] extern crate rustc; -extern crate rustc_plugin; extern crate rustc_driver; extern crate syntax; use rustc::lint::{LateContext, LintContext, LintPass, LateLintPass, LateLintPassObject, LintArray}; -use rustc_plugin::Registry; +use rustc_driver::plugin::Registry; use rustc::hir; use syntax::attr; use syntax::symbol::Symbol; diff --git a/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs b/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs index a811edd37c6..000e10392e8 100644 --- a/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs +++ b/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs @@ -4,12 +4,11 @@ #![feature(box_syntax)] #[macro_use] extern crate rustc; -extern crate rustc_plugin; extern crate rustc_driver; extern crate syntax; use rustc::lint::{LateContext, LintContext, LintPass, LateLintPass, LateLintPassObject, LintArray}; -use rustc_plugin::Registry; +use rustc_driver::plugin::Registry; use rustc::hir; use syntax::attr; use syntax::symbol::Symbol; 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 3206ddee624..a377b07bd3d 100644 --- a/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs +++ b/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs @@ -6,12 +6,11 @@ // Load rustc as a plugin to get macros. #[macro_use] extern crate rustc; -extern crate rustc_plugin; extern crate rustc_driver; use rustc::hir; use rustc::lint::{LateContext, LintContext, LintPass, LateLintPass, LateLintPassObject, LintArray}; -use rustc_plugin::Registry; +use rustc_driver::plugin::Registry; declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'"); diff --git a/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs b/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs index 4d57be49ca0..02675191f78 100644 --- a/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs +++ b/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs @@ -8,12 +8,11 @@ extern crate syntax; // Load rustc as a plugin to get macros #[macro_use] extern crate rustc; -extern crate rustc_plugin; extern crate rustc_driver; use rustc::lint::{EarlyContext, LintContext, LintPass, EarlyLintPass, EarlyLintPassObject, LintArray}; -use rustc_plugin::Registry; +use rustc_driver::plugin::Registry; use syntax::ast; declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'"); diff --git a/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs b/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs index ea7c75fbbe5..40f8d490ac8 100644 --- a/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs +++ b/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs @@ -6,11 +6,10 @@ extern crate syntax; // Load rustc as a plugin to get macros #[macro_use] extern crate rustc; -extern crate rustc_plugin; extern crate rustc_driver; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass}; -use rustc_plugin::Registry; +use rustc_driver::plugin::Registry; use syntax::ast; declare_tool_lint!(pub clippy::TEST_LINT, Warn, "Warn about stuff"); declare_tool_lint!( diff --git a/src/test/ui-fulldeps/auxiliary/llvm-pass-plugin.rs b/src/test/ui-fulldeps/auxiliary/llvm-pass-plugin.rs index 1832fee4347..2ff1c2e363d 100644 --- a/src/test/ui-fulldeps/auxiliary/llvm-pass-plugin.rs +++ b/src/test/ui-fulldeps/auxiliary/llvm-pass-plugin.rs @@ -4,10 +4,9 @@ #![feature(rustc_private)] extern crate rustc; -extern crate rustc_plugin; extern crate rustc_driver; -use rustc_plugin::Registry; +use rustc_driver::plugin::Registry; #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { diff --git a/src/test/ui-fulldeps/auxiliary/lto-syntax-extension-plugin.rs b/src/test/ui-fulldeps/auxiliary/lto-syntax-extension-plugin.rs index 6e446241d55..89bc9a2b9db 100644 --- a/src/test/ui-fulldeps/auxiliary/lto-syntax-extension-plugin.rs +++ b/src/test/ui-fulldeps/auxiliary/lto-syntax-extension-plugin.rs @@ -4,10 +4,9 @@ #![feature(rustc_private)] extern crate rustc; -extern crate rustc_plugin; extern crate rustc_driver; -use rustc_plugin::Registry; +use rustc_driver::plugin::Registry; #[plugin_registrar] pub fn plugin_registrar(_reg: &mut Registry) {} diff --git a/src/test/ui-fulldeps/auxiliary/macro-crate-test.rs b/src/test/ui-fulldeps/auxiliary/macro-crate-test.rs index d9b2740e476..ee82c0adc86 100644 --- a/src/test/ui-fulldeps/auxiliary/macro-crate-test.rs +++ b/src/test/ui-fulldeps/auxiliary/macro-crate-test.rs @@ -6,7 +6,6 @@ extern crate syntax; extern crate rustc; -extern crate rustc_plugin; extern crate rustc_driver; extern crate syntax_pos; extern crate proc_macro; diff --git a/src/test/ui-fulldeps/auxiliary/outlive-expansion-phase.rs b/src/test/ui-fulldeps/auxiliary/outlive-expansion-phase.rs index c22605afd0c..e5c4f5b8f7a 100644 --- a/src/test/ui-fulldeps/auxiliary/outlive-expansion-phase.rs +++ b/src/test/ui-fulldeps/auxiliary/outlive-expansion-phase.rs @@ -4,12 +4,11 @@ #![feature(box_syntax, rustc_private)] extern crate rustc; -extern crate rustc_plugin; extern crate rustc_driver; use std::any::Any; use std::cell::RefCell; -use rustc_plugin::Registry; +use rustc_driver::plugin::Registry; struct Foo { foo: isize diff --git a/src/test/ui-fulldeps/auxiliary/plugin-args.rs b/src/test/ui-fulldeps/auxiliary/plugin-args.rs index f3cd2397b28..5ff24cff23c 100644 --- a/src/test/ui-fulldeps/auxiliary/plugin-args.rs +++ b/src/test/ui-fulldeps/auxiliary/plugin-args.rs @@ -6,7 +6,6 @@ extern crate syntax; extern crate syntax_pos; extern crate rustc; -extern crate rustc_plugin; extern crate rustc_driver; use std::borrow::ToOwned; @@ -17,7 +16,7 @@ use syntax::print::pprust; use syntax::symbol::Symbol; use syntax_pos::Span; use syntax::tokenstream::TokenStream; -use rustc_plugin::Registry; +use rustc_driver::plugin::Registry; struct Expander { args: Vec<ast::NestedMetaItem>, diff --git a/src/test/ui-fulldeps/auxiliary/rlib-crate-test.rs b/src/test/ui-fulldeps/auxiliary/rlib-crate-test.rs index 7a91b54bf6d..1c0de98da56 100644 --- a/src/test/ui-fulldeps/auxiliary/rlib-crate-test.rs +++ b/src/test/ui-fulldeps/auxiliary/rlib-crate-test.rs @@ -4,10 +4,9 @@ #![feature(plugin_registrar, rustc_private)] extern crate rustc; -extern crate rustc_plugin; extern crate rustc_driver; -use rustc_plugin::Registry; +use rustc_driver::plugin::Registry; #[plugin_registrar] pub fn plugin_registrar(_: &mut Registry) {} diff --git a/src/test/ui-fulldeps/auxiliary/roman-numerals.rs b/src/test/ui-fulldeps/auxiliary/roman-numerals.rs index 77fa5c2cd78..027025b72b3 100644 --- a/src/test/ui-fulldeps/auxiliary/roman-numerals.rs +++ b/src/test/ui-fulldeps/auxiliary/roman-numerals.rs @@ -12,14 +12,13 @@ extern crate syntax; extern crate syntax_pos; extern crate rustc; -extern crate rustc_plugin; extern crate rustc_driver; use syntax::parse::token::{self, Token}; use syntax::tokenstream::TokenTree; use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacEager}; use syntax_pos::Span; -use rustc_plugin::Registry; +use rustc_driver::plugin::Registry; fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) -> Box<dyn MacResult + 'static> { diff --git a/src/test/ui/.gitattributes b/src/test/ui/.gitattributes index b62ade73aa9..489dc8ad111 100644 --- a/src/test/ui/.gitattributes +++ b/src/test/ui/.gitattributes @@ -1,2 +1,3 @@ lexer-crlf-line-endings-string-literal-doc-comment.rs -text trailing-carriage-return-in-string.rs -text +*.bin -text diff --git a/src/test/ui/abi-sysv64-arg-passing.rs b/src/test/ui/abi/abi-sysv64-arg-passing.rs index d40006eb9b6..d40006eb9b6 100644 --- a/src/test/ui/abi-sysv64-arg-passing.rs +++ b/src/test/ui/abi/abi-sysv64-arg-passing.rs diff --git a/src/test/ui/abi-sysv64-register-usage.rs b/src/test/ui/abi/abi-sysv64-register-usage.rs index 0c7e2d906b7..0c7e2d906b7 100644 --- a/src/test/ui/abi-sysv64-register-usage.rs +++ b/src/test/ui/abi/abi-sysv64-register-usage.rs diff --git a/src/test/ui/abort-on-c-abi.rs b/src/test/ui/abi/abort-on-c-abi.rs index cd7dd1b6a45..cd7dd1b6a45 100644 --- a/src/test/ui/abort-on-c-abi.rs +++ b/src/test/ui/abi/abort-on-c-abi.rs diff --git a/src/test/ui/anon-extern-mod.rs b/src/test/ui/abi/anon-extern-mod.rs index 37a67876c91..37a67876c91 100644 --- a/src/test/ui/anon-extern-mod.rs +++ b/src/test/ui/abi/anon-extern-mod.rs diff --git a/src/test/ui/auxiliary/anon-extern-mod-cross-crate-1.rs b/src/test/ui/abi/auxiliary/anon-extern-mod-cross-crate-1.rs index 948b5e688eb..948b5e688eb 100644 --- a/src/test/ui/auxiliary/anon-extern-mod-cross-crate-1.rs +++ b/src/test/ui/abi/auxiliary/anon-extern-mod-cross-crate-1.rs diff --git a/src/test/ui/auxiliary/foreign_lib.rs b/src/test/ui/abi/auxiliary/foreign_lib.rs index de6b0e2118a..de6b0e2118a 100644 --- a/src/test/ui/auxiliary/foreign_lib.rs +++ b/src/test/ui/abi/auxiliary/foreign_lib.rs diff --git a/src/test/ui/c-stack-as-value.rs b/src/test/ui/abi/c-stack-as-value.rs index 7595b76fb3f..7595b76fb3f 100644 --- a/src/test/ui/c-stack-as-value.rs +++ b/src/test/ui/abi/c-stack-as-value.rs diff --git a/src/test/ui/cabi-int-widening.rs b/src/test/ui/abi/cabi-int-widening.rs index 240eaebf3d6..240eaebf3d6 100644 --- a/src/test/ui/cabi-int-widening.rs +++ b/src/test/ui/abi/cabi-int-widening.rs diff --git a/src/test/ui/consts/auxiliary/anon-extern-mod-cross-crate-1.rs b/src/test/ui/abi/consts/auxiliary/anon-extern-mod-cross-crate-1.rs index 948b5e688eb..948b5e688eb 100644 --- a/src/test/ui/consts/auxiliary/anon-extern-mod-cross-crate-1.rs +++ b/src/test/ui/abi/consts/auxiliary/anon-extern-mod-cross-crate-1.rs diff --git a/src/test/ui/cross-crate/anon-extern-mod-cross-crate-2.rs b/src/test/ui/abi/cross-crate/anon-extern-mod-cross-crate-2.rs index 77168be5374..77168be5374 100644 --- a/src/test/ui/cross-crate/anon-extern-mod-cross-crate-2.rs +++ b/src/test/ui/abi/cross-crate/anon-extern-mod-cross-crate-2.rs diff --git a/src/test/ui/cross-crate/auxiliary/anon-extern-mod-cross-crate-1.rs b/src/test/ui/abi/cross-crate/auxiliary/anon-extern-mod-cross-crate-1.rs index 948b5e688eb..948b5e688eb 100644 --- a/src/test/ui/cross-crate/auxiliary/anon-extern-mod-cross-crate-1.rs +++ b/src/test/ui/abi/cross-crate/auxiliary/anon-extern-mod-cross-crate-1.rs diff --git a/src/test/ui/duplicated-external-mods.rs b/src/test/ui/abi/duplicated-external-mods.rs index 05a279a3014..05a279a3014 100644 --- a/src/test/ui/duplicated-external-mods.rs +++ b/src/test/ui/abi/duplicated-external-mods.rs diff --git a/src/test/ui/extern/auxiliary/extern-crosscrate-source.rs b/src/test/ui/abi/extern/auxiliary/extern-crosscrate-source.rs index d4568d38e25..d4568d38e25 100644 --- a/src/test/ui/extern/auxiliary/extern-crosscrate-source.rs +++ b/src/test/ui/abi/extern/auxiliary/extern-crosscrate-source.rs diff --git a/src/test/ui/extern/extern-call-deep.rs b/src/test/ui/abi/extern/extern-call-deep.rs index 81f884dada9..81f884dada9 100644 --- a/src/test/ui/extern/extern-call-deep.rs +++ b/src/test/ui/abi/extern/extern-call-deep.rs diff --git a/src/test/ui/extern/extern-call-deep2.rs b/src/test/ui/abi/extern/extern-call-deep2.rs index b31489b1e10..b31489b1e10 100644 --- a/src/test/ui/extern/extern-call-deep2.rs +++ b/src/test/ui/abi/extern/extern-call-deep2.rs diff --git a/src/test/ui/extern/extern-call-direct.rs b/src/test/ui/abi/extern/extern-call-direct.rs index 72041764215..72041764215 100644 --- a/src/test/ui/extern/extern-call-direct.rs +++ b/src/test/ui/abi/extern/extern-call-direct.rs diff --git a/src/test/ui/extern/extern-call-indirect.rs b/src/test/ui/abi/extern/extern-call-indirect.rs index 158b54e4b8c..158b54e4b8c 100644 --- a/src/test/ui/extern/extern-call-indirect.rs +++ b/src/test/ui/abi/extern/extern-call-indirect.rs diff --git a/src/test/ui/extern/extern-call-scrub.rs b/src/test/ui/abi/extern/extern-call-scrub.rs index a7b1065c9e1..a7b1065c9e1 100644 --- a/src/test/ui/extern/extern-call-scrub.rs +++ b/src/test/ui/abi/extern/extern-call-scrub.rs diff --git a/src/test/ui/extern/extern-crosscrate.rs b/src/test/ui/abi/extern/extern-crosscrate.rs index 123ce20ca26..123ce20ca26 100644 --- a/src/test/ui/extern/extern-crosscrate.rs +++ b/src/test/ui/abi/extern/extern-crosscrate.rs diff --git a/src/test/ui/extern/extern-pass-TwoU16s.rs b/src/test/ui/abi/extern/extern-pass-TwoU16s.rs index 285bce2e19c..285bce2e19c 100644 --- a/src/test/ui/extern/extern-pass-TwoU16s.rs +++ b/src/test/ui/abi/extern/extern-pass-TwoU16s.rs diff --git a/src/test/ui/extern/extern-pass-TwoU32s.rs b/src/test/ui/abi/extern/extern-pass-TwoU32s.rs index fb18aa8d22f..fb18aa8d22f 100644 --- a/src/test/ui/extern/extern-pass-TwoU32s.rs +++ b/src/test/ui/abi/extern/extern-pass-TwoU32s.rs diff --git a/src/test/ui/extern/extern-pass-TwoU64s.rs b/src/test/ui/abi/extern/extern-pass-TwoU64s.rs index 419648263aa..419648263aa 100644 --- a/src/test/ui/extern/extern-pass-TwoU64s.rs +++ b/src/test/ui/abi/extern/extern-pass-TwoU64s.rs diff --git a/src/test/ui/extern/extern-pass-TwoU8s.rs b/src/test/ui/abi/extern/extern-pass-TwoU8s.rs index 53a6a0f29f8..53a6a0f29f8 100644 --- a/src/test/ui/extern/extern-pass-TwoU8s.rs +++ b/src/test/ui/abi/extern/extern-pass-TwoU8s.rs diff --git a/src/test/ui/extern/extern-pass-char.rs b/src/test/ui/abi/extern/extern-pass-char.rs index 22f841b4552..22f841b4552 100644 --- a/src/test/ui/extern/extern-pass-char.rs +++ b/src/test/ui/abi/extern/extern-pass-char.rs diff --git a/src/test/ui/extern/extern-pass-double.rs b/src/test/ui/abi/extern/extern-pass-double.rs index dbd0a2dfa48..dbd0a2dfa48 100644 --- a/src/test/ui/extern/extern-pass-double.rs +++ b/src/test/ui/abi/extern/extern-pass-double.rs diff --git a/src/test/ui/extern/extern-pass-empty.rs b/src/test/ui/abi/extern/extern-pass-empty.rs index 07099a24204..07099a24204 100644 --- a/src/test/ui/extern/extern-pass-empty.rs +++ b/src/test/ui/abi/extern/extern-pass-empty.rs diff --git a/src/test/ui/extern/extern-pass-u32.rs b/src/test/ui/abi/extern/extern-pass-u32.rs index f2efdb7d366..f2efdb7d366 100644 --- a/src/test/ui/extern/extern-pass-u32.rs +++ b/src/test/ui/abi/extern/extern-pass-u32.rs diff --git a/src/test/ui/extern/extern-pass-u64.rs b/src/test/ui/abi/extern/extern-pass-u64.rs index 975446d430c..975446d430c 100644 --- a/src/test/ui/extern/extern-pass-u64.rs +++ b/src/test/ui/abi/extern/extern-pass-u64.rs diff --git a/src/test/ui/extern/extern-return-TwoU16s.rs b/src/test/ui/abi/extern/extern-return-TwoU16s.rs index dd884ee77fe..dd884ee77fe 100644 --- a/src/test/ui/extern/extern-return-TwoU16s.rs +++ b/src/test/ui/abi/extern/extern-return-TwoU16s.rs diff --git a/src/test/ui/extern/extern-return-TwoU32s.rs b/src/test/ui/abi/extern/extern-return-TwoU32s.rs index d6aaf5c9eaf..d6aaf5c9eaf 100644 --- a/src/test/ui/extern/extern-return-TwoU32s.rs +++ b/src/test/ui/abi/extern/extern-return-TwoU32s.rs diff --git a/src/test/ui/extern/extern-return-TwoU64s.rs b/src/test/ui/abi/extern/extern-return-TwoU64s.rs index c5e4ebadc18..c5e4ebadc18 100644 --- a/src/test/ui/extern/extern-return-TwoU64s.rs +++ b/src/test/ui/abi/extern/extern-return-TwoU64s.rs diff --git a/src/test/ui/extern/extern-return-TwoU8s.rs b/src/test/ui/abi/extern/extern-return-TwoU8s.rs index a7cd21b2073..a7cd21b2073 100644 --- a/src/test/ui/extern/extern-return-TwoU8s.rs +++ b/src/test/ui/abi/extern/extern-return-TwoU8s.rs diff --git a/src/test/ui/foreign/auxiliary/foreign_lib.rs b/src/test/ui/abi/foreign/auxiliary/foreign_lib.rs index de6b0e2118a..de6b0e2118a 100644 --- a/src/test/ui/foreign/auxiliary/foreign_lib.rs +++ b/src/test/ui/abi/foreign/auxiliary/foreign_lib.rs diff --git a/src/test/ui/foreign/foreign-call-no-runtime.rs b/src/test/ui/abi/foreign/foreign-call-no-runtime.rs index c6afa07ad05..c6afa07ad05 100644 --- a/src/test/ui/foreign/foreign-call-no-runtime.rs +++ b/src/test/ui/abi/foreign/foreign-call-no-runtime.rs diff --git a/src/test/ui/foreign/foreign-dupe.rs b/src/test/ui/abi/foreign/foreign-dupe.rs index 3c9f0f583d4..3c9f0f583d4 100644 --- a/src/test/ui/foreign/foreign-dupe.rs +++ b/src/test/ui/abi/foreign/foreign-dupe.rs diff --git a/src/test/ui/foreign/foreign-fn-with-byval.rs b/src/test/ui/abi/foreign/foreign-fn-with-byval.rs index 3a35599aa57..3a35599aa57 100644 --- a/src/test/ui/foreign/foreign-fn-with-byval.rs +++ b/src/test/ui/abi/foreign/foreign-fn-with-byval.rs diff --git a/src/test/ui/foreign/foreign-no-abi.rs b/src/test/ui/abi/foreign/foreign-no-abi.rs index 2f33fb47656..2f33fb47656 100644 --- a/src/test/ui/foreign/foreign-no-abi.rs +++ b/src/test/ui/abi/foreign/foreign-no-abi.rs diff --git a/src/test/ui/invoke-external-foreign.rs b/src/test/ui/abi/invoke-external-foreign.rs index dbd2b4ad865..dbd2b4ad865 100644 --- a/src/test/ui/invoke-external-foreign.rs +++ b/src/test/ui/abi/invoke-external-foreign.rs diff --git a/src/test/ui/lib-defaults.rs b/src/test/ui/abi/lib-defaults.rs index cd0b0bb2321..cd0b0bb2321 100644 --- a/src/test/ui/lib-defaults.rs +++ b/src/test/ui/abi/lib-defaults.rs diff --git a/src/test/ui/macros/macros-in-extern.rs b/src/test/ui/abi/macros/macros-in-extern.rs index bba8b15cdb0..bba8b15cdb0 100644 --- a/src/test/ui/macros/macros-in-extern.rs +++ b/src/test/ui/abi/macros/macros-in-extern.rs diff --git a/src/test/ui/macros/macros-in-extern.stderr b/src/test/ui/abi/macros/macros-in-extern.stderr index 6ee33f4ab61..6ee33f4ab61 100644 --- a/src/test/ui/macros/macros-in-extern.stderr +++ b/src/test/ui/abi/macros/macros-in-extern.stderr diff --git a/src/test/ui/mir/mir_codegen_calls_variadic.rs b/src/test/ui/abi/mir/mir_codegen_calls_variadic.rs index dc9fee03b77..dc9fee03b77 100644 --- a/src/test/ui/mir/mir_codegen_calls_variadic.rs +++ b/src/test/ui/abi/mir/mir_codegen_calls_variadic.rs diff --git a/src/test/ui/numbers-arithmetic/i128-ffi.rs b/src/test/ui/abi/numbers-arithmetic/i128-ffi.rs index 19edf9779f3..19edf9779f3 100644 --- a/src/test/ui/numbers-arithmetic/i128-ffi.rs +++ b/src/test/ui/abi/numbers-arithmetic/i128-ffi.rs diff --git a/src/test/ui/abi/proc-macro/auxiliary/test-macros.rs b/src/test/ui/abi/proc-macro/auxiliary/test-macros.rs new file mode 100644 index 00000000000..27efa44f980 --- /dev/null +++ b/src/test/ui/abi/proc-macro/auxiliary/test-macros.rs @@ -0,0 +1,112 @@ +// force-host +// no-prefer-dynamic + +// Proc macros commonly used by tests. +// `panic`/`print` -> `panic_bang`/`print_bang` to avoid conflicts with standard macros. + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::TokenStream; + +// Macro that return empty token stream. + +#[proc_macro] +pub fn empty(_: TokenStream) -> TokenStream { + TokenStream::new() +} + +#[proc_macro_attribute] +pub fn empty_attr(_: TokenStream, _: TokenStream) -> TokenStream { + TokenStream::new() +} + +#[proc_macro_derive(Empty, attributes(empty_helper))] +pub fn empty_derive(_: TokenStream) -> TokenStream { + TokenStream::new() +} + +// Macro that panics. + +#[proc_macro] +pub fn panic_bang(_: TokenStream) -> TokenStream { + panic!("panic-bang"); +} + +#[proc_macro_attribute] +pub fn panic_attr(_: TokenStream, _: TokenStream) -> TokenStream { + panic!("panic-attr"); +} + +#[proc_macro_derive(Panic, attributes(panic_helper))] +pub fn panic_derive(_: TokenStream) -> TokenStream { + panic!("panic-derive"); +} + +// Macros that return the input stream. + +#[proc_macro] +pub fn identity(input: TokenStream) -> TokenStream { + input +} + +#[proc_macro_attribute] +pub fn identity_attr(_: TokenStream, input: TokenStream) -> TokenStream { + input +} + +#[proc_macro_derive(Identity, attributes(identity_helper))] +pub fn identity_derive(input: TokenStream) -> TokenStream { + input +} + +// Macros that iterate and re-collect the input stream. + +#[proc_macro] +pub fn recollect(input: TokenStream) -> TokenStream { + input.into_iter().collect() +} + +#[proc_macro_attribute] +pub fn recollect_attr(_: TokenStream, input: TokenStream) -> TokenStream { + input.into_iter().collect() +} + +#[proc_macro_derive(Recollect, attributes(recollect_helper))] +pub fn recollect_derive(input: TokenStream) -> TokenStream { + input.into_iter().collect() +} + +// Macros that print their input in the original and re-collected forms (if they differ). + +fn print_helper(input: TokenStream, kind: &str) -> TokenStream { + let input_display = format!("{}", input); + let input_debug = format!("{:#?}", input); + let recollected = input.into_iter().collect(); + let recollected_display = format!("{}", recollected); + let recollected_debug = format!("{:#?}", recollected); + println!("PRINT-{} INPUT (DISPLAY): {}", kind, input_display); + if recollected_display != input_display { + println!("PRINT-{} RE-COLLECTED (DISPLAY): {}", kind, recollected_display); + } + println!("PRINT-{} INPUT (DEBUG): {}", kind, input_debug); + if recollected_debug != input_debug { + println!("PRINT-{} RE-COLLECTED (DEBUG): {}", kind, recollected_debug); + } + recollected +} + +#[proc_macro] +pub fn print_bang(input: TokenStream) -> TokenStream { + print_helper(input, "BANG") +} + +#[proc_macro_attribute] +pub fn print_attr(_: TokenStream, input: TokenStream) -> TokenStream { + print_helper(input, "ATTR") +} + +#[proc_macro_derive(Print, attributes(print_helper))] +pub fn print_derive(input: TokenStream) -> TokenStream { + print_helper(input, "DERIVE") +} diff --git a/src/test/ui/proc-macro/macros-in-extern.rs b/src/test/ui/abi/proc-macro/macros-in-extern.rs index 0477b5c48ec..0477b5c48ec 100644 --- a/src/test/ui/proc-macro/macros-in-extern.rs +++ b/src/test/ui/abi/proc-macro/macros-in-extern.rs diff --git a/src/test/ui/proc-macro/macros-in-extern.stderr b/src/test/ui/abi/proc-macro/macros-in-extern.stderr index 6049c2aa448..6049c2aa448 100644 --- a/src/test/ui/proc-macro/macros-in-extern.stderr +++ b/src/test/ui/abi/proc-macro/macros-in-extern.stderr diff --git a/src/test/ui/segfault-no-out-of-stack.rs b/src/test/ui/abi/segfault-no-out-of-stack.rs index 626de4ed5b6..626de4ed5b6 100644 --- a/src/test/ui/segfault-no-out-of-stack.rs +++ b/src/test/ui/abi/segfault-no-out-of-stack.rs diff --git a/src/test/ui/stack-probes-lto.rs b/src/test/ui/abi/stack-probes-lto.rs index 9018ff4bfc2..9018ff4bfc2 100644 --- a/src/test/ui/stack-probes-lto.rs +++ b/src/test/ui/abi/stack-probes-lto.rs diff --git a/src/test/ui/stack-probes.rs b/src/test/ui/abi/stack-probes.rs index 1ab1d6df66d..1ab1d6df66d 100644 --- a/src/test/ui/stack-probes.rs +++ b/src/test/ui/abi/stack-probes.rs diff --git a/src/test/ui/statics/static-mut-foreign.rs b/src/test/ui/abi/statics/static-mut-foreign.rs index 5d6fa416b98..5d6fa416b98 100644 --- a/src/test/ui/statics/static-mut-foreign.rs +++ b/src/test/ui/abi/statics/static-mut-foreign.rs diff --git a/src/test/ui/structs-enums/struct-return.rs b/src/test/ui/abi/struct-enums/struct-return.rs index 5930fc4acbb..5930fc4acbb 100644 --- a/src/test/ui/structs-enums/struct-return.rs +++ b/src/test/ui/abi/struct-enums/struct-return.rs diff --git a/src/test/ui/union/union-c-interop.rs b/src/test/ui/abi/union/union-c-interop.rs index 00f04d5b7ff..00f04d5b7ff 100644 --- a/src/test/ui/union/union-c-interop.rs +++ b/src/test/ui/abi/union/union-c-interop.rs diff --git a/src/test/ui/variadic-ffi.rs b/src/test/ui/abi/variadic-ffi.rs index 3232a11d726..3232a11d726 100644 --- a/src/test/ui/variadic-ffi.rs +++ b/src/test/ui/abi/variadic-ffi.rs diff --git a/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs b/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs new file mode 100644 index 00000000000..a58cec53421 --- /dev/null +++ b/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.rs @@ -0,0 +1,32 @@ +// This test documents that `type Out = Box<dyn Bar<Assoc: Copy>>;` +// is allowed and will correctly reject an opaque `type Out` which +// does not satisfy the bound `<TheType as Bar>::Assoc: Copy`. +// +// FIXME(rust-lang/lang): I think this behavior is logical if we want to allow +// `dyn Trait<Assoc: Bound>` but we should decide if we want that. // Centril +// +// Additionally, as reported in https://github.com/rust-lang/rust/issues/63594, +// we check that the spans for the error message are sane here. + +#![feature(associated_type_bounds)] + +fn main() {} + +trait Bar { type Assoc; } + +trait Thing { + type Out; + fn func() -> Self::Out; +} + +struct AssocNoCopy; +impl Bar for AssocNoCopy { type Assoc = String; } + +impl Thing for AssocNoCopy { + type Out = Box<dyn Bar<Assoc: Copy>>; + //~^ ERROR the trait bound `std::string::String: std::marker::Copy` is not satisfied + + fn func() -> Self::Out { + Box::new(AssocNoCopy) + } +} diff --git a/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr b/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr new file mode 100644 index 00000000000..b6b49c2e903 --- /dev/null +++ b/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr @@ -0,0 +1,11 @@ +error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied + --> $DIR/assoc-type-eq-with-dyn-atb-fail.rs:26:28 + | +LL | type Out = Box<dyn Bar<Assoc: Copy>>; + | ^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String` + | + = note: the return type of a function must have a statically known size + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-type-bounds/duplicate.rs b/src/test/ui/associated-type-bounds/duplicate.rs index 1f2d755ed71..a89fd9807da 100644 --- a/src/test/ui/associated-type-bounds/duplicate.rs +++ b/src/test/ui/associated-type-bounds/duplicate.rs @@ -1,161 +1,184 @@ // compile-fail // ignore-tidy-linelength -// error-pattern:could not find defining uses #![feature(associated_type_bounds)] #![feature(type_alias_impl_trait)] -#![feature(impl_trait_in_bindings)] +#![feature(impl_trait_in_bindings)] //~ WARN the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash [incomplete_features] #![feature(untagged_unions)] use std::iter; struct SI1<T: Iterator<Item: Copy, Item: Send>> { f: T } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] struct SI2<T: Iterator<Item: Copy, Item: Copy>> { f: T } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] struct SI3<T: Iterator<Item: 'static, Item: 'static>> { f: T } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] struct SW1<T> where T: Iterator<Item: Copy, Item: Send> { f: T } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] struct SW2<T> where T: Iterator<Item: Copy, Item: Copy> { f: T } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] struct SW3<T> where T: Iterator<Item: 'static, Item: 'static> { f: T } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] enum EI1<T: Iterator<Item: Copy, Item: Send>> { V(T) } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] enum EI2<T: Iterator<Item: Copy, Item: Copy>> { V(T) } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] enum EI3<T: Iterator<Item: 'static, Item: 'static>> { V(T) } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] enum EW1<T> where T: Iterator<Item: Copy, Item: Send> { V(T) } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] enum EW2<T> where T: Iterator<Item: Copy, Item: Copy> { V(T) } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] enum EW3<T> where T: Iterator<Item: 'static, Item: 'static> { V(T) } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] union UI1<T: Iterator<Item: Copy, Item: Send>> { f: T } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] union UI2<T: Iterator<Item: Copy, Item: Copy>> { f: T } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] union UI3<T: Iterator<Item: 'static, Item: 'static>> { f: T } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] union UW1<T> where T: Iterator<Item: Copy, Item: Send> { f: T } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] union UW2<T> where T: Iterator<Item: Copy, Item: Copy> { f: T } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] union UW3<T> where T: Iterator<Item: 'static, Item: 'static> { f: T } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] fn FI1<T: Iterator<Item: Copy, Item: Send>>() {} -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] fn FI2<T: Iterator<Item: Copy, Item: Copy>>() {} -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] fn FI3<T: Iterator<Item: 'static, Item: 'static>>() {} -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] fn FW1<T>() where T: Iterator<Item: Copy, Item: Send> {} -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] fn FW2<T>() where T: Iterator<Item: Copy, Item: Copy> {} -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] fn FW3<T>() where T: Iterator<Item: 'static, Item: 'static> {} -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] fn FRPIT1() -> impl Iterator<Item: Copy, Item: Send> { iter::empty() } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] fn FRPIT2() -> impl Iterator<Item: Copy, Item: Copy> { iter::empty() } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] fn FRPIT3() -> impl Iterator<Item: 'static, Item: 'static> { iter::empty() } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] fn FAPIT1(_: impl Iterator<Item: Copy, Item: Send>) {} -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] fn FAPIT2(_: impl Iterator<Item: Copy, Item: Copy>) {} -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] fn FAPIT3(_: impl Iterator<Item: 'static, Item: 'static>) {} -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] const CIT1: impl Iterator<Item: Copy, Item: Send> = iter::empty(); -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] const CIT2: impl Iterator<Item: Copy, Item: Copy> = iter::empty(); -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] const CIT3: impl Iterator<Item: 'static, Item: 'static> = iter::empty(); -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] static SIT1: impl Iterator<Item: Copy, Item: Send> = iter::empty(); -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] static SIT2: impl Iterator<Item: Copy, Item: Copy> = iter::empty(); -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] static SIT3: impl Iterator<Item: 'static, Item: 'static> = iter::empty(); -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] fn lit1() { let _: impl Iterator<Item: Copy, Item: Send> = iter::empty(); } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] fn lit2() { let _: impl Iterator<Item: Copy, Item: Copy> = iter::empty(); } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] fn lit3() { let _: impl Iterator<Item: 'static, Item: 'static> = iter::empty(); } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] type TAI1<T: Iterator<Item: Copy, Item: Send>> = T; -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] type TAI2<T: Iterator<Item: Copy, Item: Copy>> = T; -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] type TAI3<T: Iterator<Item: 'static, Item: 'static>> = T; -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] type TAW1<T> where T: Iterator<Item: Copy, Item: Send> = T; -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] type TAW2<T> where T: Iterator<Item: Copy, Item: Copy> = T; -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] type TAW3<T> where T: Iterator<Item: 'static, Item: 'static> = T; -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] type ETAI1<T: Iterator<Item: Copy, Item: Send>> = impl Copy; -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~| ERROR could not find defining uses +//~| ERROR could not find defining uses +//~| ERROR could not find defining uses type ETAI2<T: Iterator<Item: Copy, Item: Copy>> = impl Copy; -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~| ERROR could not find defining uses +//~| ERROR could not find defining uses +//~| ERROR could not find defining uses type ETAI3<T: Iterator<Item: 'static, Item: 'static>> = impl Copy; -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~| ERROR could not find defining uses +//~| ERROR could not find defining uses +//~| ERROR could not find defining uses type ETAI4 = impl Iterator<Item: Copy, Item: Send>; -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~| ERROR could not find defining uses +//~| ERROR could not find defining uses +//~| ERROR could not find defining uses type ETAI5 = impl Iterator<Item: Copy, Item: Copy>; -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~| ERROR could not find defining uses +//~| ERROR could not find defining uses +//~| ERROR could not find defining uses type ETAI6 = impl Iterator<Item: 'static, Item: 'static>; -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~| ERROR could not find defining uses +//~| ERROR could not find defining uses +//~| ERROR could not find defining uses trait TRI1<T: Iterator<Item: Copy, Item: Send>> {} -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] trait TRI2<T: Iterator<Item: Copy, Item: Copy>> {} -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] trait TRI3<T: Iterator<Item: 'static, Item: 'static>> {} -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] trait TRS1: Iterator<Item: Copy, Item: Send> {} -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] trait TRS2: Iterator<Item: Copy, Item: Copy> {} -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] trait TRS3: Iterator<Item: 'static, Item: 'static> {} -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] trait TRW1<T> where T: Iterator<Item: Copy, Item: Send> {} -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] trait TRW2<T> where T: Iterator<Item: Copy, Item: Copy> {} -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] trait TRW3<T> where T: Iterator<Item: 'static, Item: 'static> {} -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] trait TRSW1 where Self: Iterator<Item: Copy, Item: Send> {} -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] trait TRSW2 where Self: Iterator<Item: Copy, Item: Copy> {} -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] trait TRSW3 where Self: Iterator<Item: 'static, Item: 'static> {} -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] trait TRA1 { type A: Iterator<Item: Copy, Item: Send>; } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] trait TRA2 { type A: Iterator<Item: Copy, Item: Copy>; } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] trait TRA3 { type A: Iterator<Item: 'static, Item: 'static>; } -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] type TADyn1 = dyn Iterator<Item: Copy, Item: Send>; -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~| ERROR could not find defining uses +//~| ERROR could not find defining uses type TADyn2 = Box<dyn Iterator<Item: Copy, Item: Copy>>; -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~| ERROR could not find defining uses +//~| ERROR could not find defining uses type TADyn3 = dyn Iterator<Item: 'static, Item: 'static>; -//~^ the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~^ ERROR the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified [E0719] +//~| ERROR could not find defining uses +//~| ERROR could not find defining uses fn main() {} diff --git a/src/test/ui/associated-type-bounds/duplicate.stderr b/src/test/ui/associated-type-bounds/duplicate.stderr index 7f3a65ab696..e5e85d6856f 100644 --- a/src/test/ui/associated-type-bounds/duplicate.stderr +++ b/src/test/ui/associated-type-bounds/duplicate.stderr @@ -1,5 +1,5 @@ warning: the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash - --> $DIR/duplicate.rs:7:12 + --> $DIR/duplicate.rs:6:12 | LL | #![feature(impl_trait_in_bindings)] | ^^^^^^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | #![feature(impl_trait_in_bindings)] = note: `#[warn(incomplete_features)]` on by default error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:12:36 + --> $DIR/duplicate.rs:11:36 | LL | struct SI1<T: Iterator<Item: Copy, Item: Send>> { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -15,7 +15,7 @@ LL | struct SI1<T: Iterator<Item: Copy, Item: Send>> { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:14:36 + --> $DIR/duplicate.rs:13:36 | LL | struct SI2<T: Iterator<Item: Copy, Item: Copy>> { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -23,7 +23,7 @@ LL | struct SI2<T: Iterator<Item: Copy, Item: Copy>> { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:16:39 + --> $DIR/duplicate.rs:15:39 | LL | struct SI3<T: Iterator<Item: 'static, Item: 'static>> { f: T } | ------------- ^^^^^^^^^^^^^ re-bound here @@ -31,7 +31,7 @@ LL | struct SI3<T: Iterator<Item: 'static, Item: 'static>> { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:18:45 + --> $DIR/duplicate.rs:17:45 | LL | struct SW1<T> where T: Iterator<Item: Copy, Item: Send> { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -39,7 +39,7 @@ LL | struct SW1<T> where T: Iterator<Item: Copy, Item: Send> { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:20:45 + --> $DIR/duplicate.rs:19:45 | LL | struct SW2<T> where T: Iterator<Item: Copy, Item: Copy> { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -47,7 +47,7 @@ LL | struct SW2<T> where T: Iterator<Item: Copy, Item: Copy> { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:22:48 + --> $DIR/duplicate.rs:21:48 | LL | struct SW3<T> where T: Iterator<Item: 'static, Item: 'static> { f: T } | ------------- ^^^^^^^^^^^^^ re-bound here @@ -55,7 +55,7 @@ LL | struct SW3<T> where T: Iterator<Item: 'static, Item: 'static> { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:25:34 + --> $DIR/duplicate.rs:24:34 | LL | enum EI1<T: Iterator<Item: Copy, Item: Send>> { V(T) } | ---------- ^^^^^^^^^^ re-bound here @@ -63,7 +63,7 @@ LL | enum EI1<T: Iterator<Item: Copy, Item: Send>> { V(T) } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:27:34 + --> $DIR/duplicate.rs:26:34 | LL | enum EI2<T: Iterator<Item: Copy, Item: Copy>> { V(T) } | ---------- ^^^^^^^^^^ re-bound here @@ -71,7 +71,7 @@ LL | enum EI2<T: Iterator<Item: Copy, Item: Copy>> { V(T) } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:29:37 + --> $DIR/duplicate.rs:28:37 | LL | enum EI3<T: Iterator<Item: 'static, Item: 'static>> { V(T) } | ------------- ^^^^^^^^^^^^^ re-bound here @@ -79,7 +79,7 @@ LL | enum EI3<T: Iterator<Item: 'static, Item: 'static>> { V(T) } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:31:43 + --> $DIR/duplicate.rs:30:43 | LL | enum EW1<T> where T: Iterator<Item: Copy, Item: Send> { V(T) } | ---------- ^^^^^^^^^^ re-bound here @@ -87,7 +87,7 @@ LL | enum EW1<T> where T: Iterator<Item: Copy, Item: Send> { V(T) } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:33:43 + --> $DIR/duplicate.rs:32:43 | LL | enum EW2<T> where T: Iterator<Item: Copy, Item: Copy> { V(T) } | ---------- ^^^^^^^^^^ re-bound here @@ -95,7 +95,7 @@ LL | enum EW2<T> where T: Iterator<Item: Copy, Item: Copy> { V(T) } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:35:46 + --> $DIR/duplicate.rs:34:46 | LL | enum EW3<T> where T: Iterator<Item: 'static, Item: 'static> { V(T) } | ------------- ^^^^^^^^^^^^^ re-bound here @@ -103,7 +103,7 @@ LL | enum EW3<T> where T: Iterator<Item: 'static, Item: 'static> { V(T) } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:38:35 + --> $DIR/duplicate.rs:37:35 | LL | union UI1<T: Iterator<Item: Copy, Item: Send>> { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -111,7 +111,7 @@ LL | union UI1<T: Iterator<Item: Copy, Item: Send>> { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:40:35 + --> $DIR/duplicate.rs:39:35 | LL | union UI2<T: Iterator<Item: Copy, Item: Copy>> { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -119,7 +119,7 @@ LL | union UI2<T: Iterator<Item: Copy, Item: Copy>> { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:42:38 + --> $DIR/duplicate.rs:41:38 | LL | union UI3<T: Iterator<Item: 'static, Item: 'static>> { f: T } | ------------- ^^^^^^^^^^^^^ re-bound here @@ -127,7 +127,7 @@ LL | union UI3<T: Iterator<Item: 'static, Item: 'static>> { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:44:44 + --> $DIR/duplicate.rs:43:44 | LL | union UW1<T> where T: Iterator<Item: Copy, Item: Send> { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -135,7 +135,7 @@ LL | union UW1<T> where T: Iterator<Item: Copy, Item: Send> { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:46:44 + --> $DIR/duplicate.rs:45:44 | LL | union UW2<T> where T: Iterator<Item: Copy, Item: Copy> { f: T } | ---------- ^^^^^^^^^^ re-bound here @@ -143,7 +143,7 @@ LL | union UW2<T> where T: Iterator<Item: Copy, Item: Copy> { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:48:47 + --> $DIR/duplicate.rs:47:47 | LL | union UW3<T> where T: Iterator<Item: 'static, Item: 'static> { f: T } | ------------- ^^^^^^^^^^^^^ re-bound here @@ -151,7 +151,7 @@ LL | union UW3<T> where T: Iterator<Item: 'static, Item: 'static> { f: T } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:51:32 + --> $DIR/duplicate.rs:50:32 | LL | fn FI1<T: Iterator<Item: Copy, Item: Send>>() {} | ---------- ^^^^^^^^^^ re-bound here @@ -159,7 +159,7 @@ LL | fn FI1<T: Iterator<Item: Copy, Item: Send>>() {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:53:32 + --> $DIR/duplicate.rs:52:32 | LL | fn FI2<T: Iterator<Item: Copy, Item: Copy>>() {} | ---------- ^^^^^^^^^^ re-bound here @@ -167,7 +167,7 @@ LL | fn FI2<T: Iterator<Item: Copy, Item: Copy>>() {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:55:35 + --> $DIR/duplicate.rs:54:35 | LL | fn FI3<T: Iterator<Item: 'static, Item: 'static>>() {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -175,7 +175,7 @@ LL | fn FI3<T: Iterator<Item: 'static, Item: 'static>>() {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:57:43 + --> $DIR/duplicate.rs:56:43 | LL | fn FW1<T>() where T: Iterator<Item: Copy, Item: Send> {} | ---------- ^^^^^^^^^^ re-bound here @@ -183,7 +183,7 @@ LL | fn FW1<T>() where T: Iterator<Item: Copy, Item: Send> {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:59:43 + --> $DIR/duplicate.rs:58:43 | LL | fn FW2<T>() where T: Iterator<Item: Copy, Item: Copy> {} | ---------- ^^^^^^^^^^ re-bound here @@ -191,7 +191,7 @@ LL | fn FW2<T>() where T: Iterator<Item: Copy, Item: Copy> {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:61:46 + --> $DIR/duplicate.rs:60:46 | LL | fn FW3<T>() where T: Iterator<Item: 'static, Item: 'static> {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -199,7 +199,7 @@ LL | fn FW3<T>() where T: Iterator<Item: 'static, Item: 'static> {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:70:40 + --> $DIR/duplicate.rs:69:40 | LL | fn FAPIT1(_: impl Iterator<Item: Copy, Item: Send>) {} | ---------- ^^^^^^^^^^ re-bound here @@ -207,7 +207,7 @@ LL | fn FAPIT1(_: impl Iterator<Item: Copy, Item: Send>) {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:72:40 + --> $DIR/duplicate.rs:71:40 | LL | fn FAPIT2(_: impl Iterator<Item: Copy, Item: Copy>) {} | ---------- ^^^^^^^^^^ re-bound here @@ -215,7 +215,7 @@ LL | fn FAPIT2(_: impl Iterator<Item: Copy, Item: Copy>) {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:74:43 + --> $DIR/duplicate.rs:73:43 | LL | fn FAPIT3(_: impl Iterator<Item: 'static, Item: 'static>) {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -223,7 +223,7 @@ LL | fn FAPIT3(_: impl Iterator<Item: 'static, Item: 'static>) {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:64:42 + --> $DIR/duplicate.rs:63:42 | LL | fn FRPIT1() -> impl Iterator<Item: Copy, Item: Send> { iter::empty() } | ---------- ^^^^^^^^^^ re-bound here @@ -231,7 +231,7 @@ LL | fn FRPIT1() -> impl Iterator<Item: Copy, Item: Send> { iter::empty() } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:66:42 + --> $DIR/duplicate.rs:65:42 | LL | fn FRPIT2() -> impl Iterator<Item: Copy, Item: Copy> { iter::empty() } | ---------- ^^^^^^^^^^ re-bound here @@ -239,7 +239,7 @@ LL | fn FRPIT2() -> impl Iterator<Item: Copy, Item: Copy> { iter::empty() } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:68:45 + --> $DIR/duplicate.rs:67:45 | LL | fn FRPIT3() -> impl Iterator<Item: 'static, Item: 'static> { iter::empty() } | ------------- ^^^^^^^^^^^^^ re-bound here @@ -247,7 +247,7 @@ LL | fn FRPIT3() -> impl Iterator<Item: 'static, Item: 'static> { iter::empty() | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:77:39 + --> $DIR/duplicate.rs:76:39 | LL | const CIT1: impl Iterator<Item: Copy, Item: Send> = iter::empty(); | ---------- ^^^^^^^^^^ re-bound here @@ -255,7 +255,7 @@ LL | const CIT1: impl Iterator<Item: Copy, Item: Send> = iter::empty(); | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:79:39 + --> $DIR/duplicate.rs:78:39 | LL | const CIT2: impl Iterator<Item: Copy, Item: Copy> = iter::empty(); | ---------- ^^^^^^^^^^ re-bound here @@ -263,7 +263,7 @@ LL | const CIT2: impl Iterator<Item: Copy, Item: Copy> = iter::empty(); | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:81:42 + --> $DIR/duplicate.rs:80:42 | LL | const CIT3: impl Iterator<Item: 'static, Item: 'static> = iter::empty(); | ------------- ^^^^^^^^^^^^^ re-bound here @@ -271,7 +271,7 @@ LL | const CIT3: impl Iterator<Item: 'static, Item: 'static> = iter::empty(); | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:83:40 + --> $DIR/duplicate.rs:82:40 | LL | static SIT1: impl Iterator<Item: Copy, Item: Send> = iter::empty(); | ---------- ^^^^^^^^^^ re-bound here @@ -279,7 +279,7 @@ LL | static SIT1: impl Iterator<Item: Copy, Item: Send> = iter::empty(); | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:85:40 + --> $DIR/duplicate.rs:84:40 | LL | static SIT2: impl Iterator<Item: Copy, Item: Copy> = iter::empty(); | ---------- ^^^^^^^^^^ re-bound here @@ -287,7 +287,7 @@ LL | static SIT2: impl Iterator<Item: Copy, Item: Copy> = iter::empty(); | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:87:43 + --> $DIR/duplicate.rs:86:43 | LL | static SIT3: impl Iterator<Item: 'static, Item: 'static> = iter::empty(); | ------------- ^^^^^^^^^^^^^ re-bound here @@ -295,7 +295,7 @@ LL | static SIT3: impl Iterator<Item: 'static, Item: 'static> = iter::empty(); | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:90:46 + --> $DIR/duplicate.rs:89:46 | LL | fn lit1() { let _: impl Iterator<Item: Copy, Item: Send> = iter::empty(); } | ---------- ^^^^^^^^^^ re-bound here @@ -303,7 +303,7 @@ LL | fn lit1() { let _: impl Iterator<Item: Copy, Item: Send> = iter::empty(); } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:92:46 + --> $DIR/duplicate.rs:91:46 | LL | fn lit2() { let _: impl Iterator<Item: Copy, Item: Copy> = iter::empty(); } | ---------- ^^^^^^^^^^ re-bound here @@ -311,7 +311,7 @@ LL | fn lit2() { let _: impl Iterator<Item: Copy, Item: Copy> = iter::empty(); } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:94:49 + --> $DIR/duplicate.rs:93:49 | LL | fn lit3() { let _: impl Iterator<Item: 'static, Item: 'static> = iter::empty(); } | ------------- ^^^^^^^^^^^^^ re-bound here @@ -319,7 +319,7 @@ LL | fn lit3() { let _: impl Iterator<Item: 'static, Item: 'static> = iter::empt | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:97:35 + --> $DIR/duplicate.rs:96:35 | LL | type TAI1<T: Iterator<Item: Copy, Item: Send>> = T; | ---------- ^^^^^^^^^^ re-bound here @@ -327,7 +327,7 @@ LL | type TAI1<T: Iterator<Item: Copy, Item: Send>> = T; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:99:35 + --> $DIR/duplicate.rs:98:35 | LL | type TAI2<T: Iterator<Item: Copy, Item: Copy>> = T; | ---------- ^^^^^^^^^^ re-bound here @@ -335,7 +335,7 @@ LL | type TAI2<T: Iterator<Item: Copy, Item: Copy>> = T; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:101:38 + --> $DIR/duplicate.rs:100:38 | LL | type TAI3<T: Iterator<Item: 'static, Item: 'static>> = T; | ------------- ^^^^^^^^^^^^^ re-bound here @@ -343,7 +343,7 @@ LL | type TAI3<T: Iterator<Item: 'static, Item: 'static>> = T; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:103:44 + --> $DIR/duplicate.rs:102:44 | LL | type TAW1<T> where T: Iterator<Item: Copy, Item: Send> = T; | ---------- ^^^^^^^^^^ re-bound here @@ -351,7 +351,7 @@ LL | type TAW1<T> where T: Iterator<Item: Copy, Item: Send> = T; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:105:44 + --> $DIR/duplicate.rs:104:44 | LL | type TAW2<T> where T: Iterator<Item: Copy, Item: Copy> = T; | ---------- ^^^^^^^^^^ re-bound here @@ -359,7 +359,7 @@ LL | type TAW2<T> where T: Iterator<Item: Copy, Item: Copy> = T; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:107:47 + --> $DIR/duplicate.rs:106:47 | LL | type TAW3<T> where T: Iterator<Item: 'static, Item: 'static> = T; | ------------- ^^^^^^^^^^^^^ re-bound here @@ -367,13 +367,13 @@ LL | type TAW3<T> where T: Iterator<Item: 'static, Item: 'static> = T; | `Item` bound here first error: could not find defining uses - --> $DIR/duplicate.rs:110:1 + --> $DIR/duplicate.rs:109:1 | LL | type ETAI1<T: Iterator<Item: Copy, Item: Send>> = impl Copy; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:110:36 + --> $DIR/duplicate.rs:109:36 | LL | type ETAI1<T: Iterator<Item: Copy, Item: Send>> = impl Copy; | ---------- ^^^^^^^^^^ re-bound here @@ -381,13 +381,13 @@ LL | type ETAI1<T: Iterator<Item: Copy, Item: Send>> = impl Copy; | `Item` bound here first error: could not find defining uses - --> $DIR/duplicate.rs:112:1 + --> $DIR/duplicate.rs:114:1 | LL | type ETAI2<T: Iterator<Item: Copy, Item: Copy>> = impl Copy; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:112:36 + --> $DIR/duplicate.rs:114:36 | LL | type ETAI2<T: Iterator<Item: Copy, Item: Copy>> = impl Copy; | ---------- ^^^^^^^^^^ re-bound here @@ -395,13 +395,13 @@ LL | type ETAI2<T: Iterator<Item: Copy, Item: Copy>> = impl Copy; | `Item` bound here first error: could not find defining uses - --> $DIR/duplicate.rs:114:1 + --> $DIR/duplicate.rs:119:1 | LL | type ETAI3<T: Iterator<Item: 'static, Item: 'static>> = impl Copy; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:114:39 + --> $DIR/duplicate.rs:119:39 | LL | type ETAI3<T: Iterator<Item: 'static, Item: 'static>> = impl Copy; | ------------- ^^^^^^^^^^^^^ re-bound here @@ -409,13 +409,13 @@ LL | type ETAI3<T: Iterator<Item: 'static, Item: 'static>> = impl Copy; | `Item` bound here first error: could not find defining uses - --> $DIR/duplicate.rs:116:1 + --> $DIR/duplicate.rs:124:1 | LL | type ETAI4 = impl Iterator<Item: Copy, Item: Send>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:116:40 + --> $DIR/duplicate.rs:124:40 | LL | type ETAI4 = impl Iterator<Item: Copy, Item: Send>; | ---------- ^^^^^^^^^^ re-bound here @@ -423,13 +423,13 @@ LL | type ETAI4 = impl Iterator<Item: Copy, Item: Send>; | `Item` bound here first error: could not find defining uses - --> $DIR/duplicate.rs:118:1 + --> $DIR/duplicate.rs:129:1 | LL | type ETAI5 = impl Iterator<Item: Copy, Item: Copy>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:118:40 + --> $DIR/duplicate.rs:129:40 | LL | type ETAI5 = impl Iterator<Item: Copy, Item: Copy>; | ---------- ^^^^^^^^^^ re-bound here @@ -437,13 +437,13 @@ LL | type ETAI5 = impl Iterator<Item: Copy, Item: Copy>; | `Item` bound here first error: could not find defining uses - --> $DIR/duplicate.rs:120:1 + --> $DIR/duplicate.rs:134:1 | LL | type ETAI6 = impl Iterator<Item: 'static, Item: 'static>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:120:43 + --> $DIR/duplicate.rs:134:43 | LL | type ETAI6 = impl Iterator<Item: 'static, Item: 'static>; | ------------- ^^^^^^^^^^^^^ re-bound here @@ -451,7 +451,7 @@ LL | type ETAI6 = impl Iterator<Item: 'static, Item: 'static>; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:123:36 + --> $DIR/duplicate.rs:140:36 | LL | trait TRI1<T: Iterator<Item: Copy, Item: Send>> {} | ---------- ^^^^^^^^^^ re-bound here @@ -459,7 +459,7 @@ LL | trait TRI1<T: Iterator<Item: Copy, Item: Send>> {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:125:36 + --> $DIR/duplicate.rs:142:36 | LL | trait TRI2<T: Iterator<Item: Copy, Item: Copy>> {} | ---------- ^^^^^^^^^^ re-bound here @@ -467,7 +467,7 @@ LL | trait TRI2<T: Iterator<Item: Copy, Item: Copy>> {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:127:39 + --> $DIR/duplicate.rs:144:39 | LL | trait TRI3<T: Iterator<Item: 'static, Item: 'static>> {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -475,7 +475,7 @@ LL | trait TRI3<T: Iterator<Item: 'static, Item: 'static>> {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:129:34 + --> $DIR/duplicate.rs:146:34 | LL | trait TRS1: Iterator<Item: Copy, Item: Send> {} | ---------- ^^^^^^^^^^ re-bound here @@ -483,7 +483,7 @@ LL | trait TRS1: Iterator<Item: Copy, Item: Send> {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:131:34 + --> $DIR/duplicate.rs:148:34 | LL | trait TRS2: Iterator<Item: Copy, Item: Copy> {} | ---------- ^^^^^^^^^^ re-bound here @@ -491,7 +491,7 @@ LL | trait TRS2: Iterator<Item: Copy, Item: Copy> {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:133:37 + --> $DIR/duplicate.rs:150:37 | LL | trait TRS3: Iterator<Item: 'static, Item: 'static> {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -499,7 +499,7 @@ LL | trait TRS3: Iterator<Item: 'static, Item: 'static> {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:135:45 + --> $DIR/duplicate.rs:152:45 | LL | trait TRW1<T> where T: Iterator<Item: Copy, Item: Send> {} | ---------- ^^^^^^^^^^ re-bound here @@ -507,7 +507,7 @@ LL | trait TRW1<T> where T: Iterator<Item: Copy, Item: Send> {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:137:45 + --> $DIR/duplicate.rs:154:45 | LL | trait TRW2<T> where T: Iterator<Item: Copy, Item: Copy> {} | ---------- ^^^^^^^^^^ re-bound here @@ -515,7 +515,7 @@ LL | trait TRW2<T> where T: Iterator<Item: Copy, Item: Copy> {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:139:48 + --> $DIR/duplicate.rs:156:48 | LL | trait TRW3<T> where T: Iterator<Item: 'static, Item: 'static> {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -523,7 +523,7 @@ LL | trait TRW3<T> where T: Iterator<Item: 'static, Item: 'static> {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:141:46 + --> $DIR/duplicate.rs:158:46 | LL | trait TRSW1 where Self: Iterator<Item: Copy, Item: Send> {} | ---------- ^^^^^^^^^^ re-bound here @@ -531,7 +531,7 @@ LL | trait TRSW1 where Self: Iterator<Item: Copy, Item: Send> {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:143:46 + --> $DIR/duplicate.rs:160:46 | LL | trait TRSW2 where Self: Iterator<Item: Copy, Item: Copy> {} | ---------- ^^^^^^^^^^ re-bound here @@ -539,7 +539,7 @@ LL | trait TRSW2 where Self: Iterator<Item: Copy, Item: Copy> {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:145:49 + --> $DIR/duplicate.rs:162:49 | LL | trait TRSW3 where Self: Iterator<Item: 'static, Item: 'static> {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -547,7 +547,7 @@ LL | trait TRSW3 where Self: Iterator<Item: 'static, Item: 'static> {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:147:43 + --> $DIR/duplicate.rs:164:43 | LL | trait TRA1 { type A: Iterator<Item: Copy, Item: Send>; } | ---------- ^^^^^^^^^^ re-bound here @@ -555,7 +555,7 @@ LL | trait TRA1 { type A: Iterator<Item: Copy, Item: Send>; } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:149:43 + --> $DIR/duplicate.rs:166:43 | LL | trait TRA2 { type A: Iterator<Item: Copy, Item: Copy>; } | ---------- ^^^^^^^^^^ re-bound here @@ -563,7 +563,7 @@ LL | trait TRA2 { type A: Iterator<Item: Copy, Item: Copy>; } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:151:46 + --> $DIR/duplicate.rs:168:46 | LL | trait TRA3 { type A: Iterator<Item: 'static, Item: 'static>; } | ------------- ^^^^^^^^^^^^^ re-bound here @@ -571,7 +571,7 @@ LL | trait TRA3 { type A: Iterator<Item: 'static, Item: 'static>; } | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:154:40 + --> $DIR/duplicate.rs:171:40 | LL | type TADyn1 = dyn Iterator<Item: Copy, Item: Send>; | ---------- ^^^^^^^^^^ re-bound here @@ -579,7 +579,7 @@ LL | type TADyn1 = dyn Iterator<Item: Copy, Item: Send>; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:156:44 + --> $DIR/duplicate.rs:175:44 | LL | type TADyn2 = Box<dyn Iterator<Item: Copy, Item: Copy>>; | ---------- ^^^^^^^^^^ re-bound here @@ -587,7 +587,7 @@ LL | type TADyn2 = Box<dyn Iterator<Item: Copy, Item: Copy>>; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified - --> $DIR/duplicate.rs:158:43 + --> $DIR/duplicate.rs:179:43 | LL | type TADyn3 = dyn Iterator<Item: 'static, Item: 'static>; | ------------- ^^^^^^^^^^^^^ re-bound here @@ -595,40 +595,112 @@ LL | type TADyn3 = dyn Iterator<Item: 'static, Item: 'static>; | `Item` bound here first error: could not find defining uses + --> $DIR/duplicate.rs:109:24 + | +LL | type ETAI1<T: Iterator<Item: Copy, Item: Send>> = impl Copy; + | ^^^^^^^^^^ error: could not find defining uses + --> $DIR/duplicate.rs:109:36 + | +LL | type ETAI1<T: Iterator<Item: Copy, Item: Send>> = impl Copy; + | ^^^^^^^^^^ error: could not find defining uses + --> $DIR/duplicate.rs:114:24 + | +LL | type ETAI2<T: Iterator<Item: Copy, Item: Copy>> = impl Copy; + | ^^^^^^^^^^ error: could not find defining uses + --> $DIR/duplicate.rs:114:36 + | +LL | type ETAI2<T: Iterator<Item: Copy, Item: Copy>> = impl Copy; + | ^^^^^^^^^^ error: could not find defining uses + --> $DIR/duplicate.rs:119:24 + | +LL | type ETAI3<T: Iterator<Item: 'static, Item: 'static>> = impl Copy; + | ^^^^^^^^^^^^^ error: could not find defining uses + --> $DIR/duplicate.rs:119:39 + | +LL | type ETAI3<T: Iterator<Item: 'static, Item: 'static>> = impl Copy; + | ^^^^^^^^^^^^^ error: could not find defining uses + --> $DIR/duplicate.rs:124:28 + | +LL | type ETAI4 = impl Iterator<Item: Copy, Item: Send>; + | ^^^^^^^^^^ error: could not find defining uses + --> $DIR/duplicate.rs:124:40 + | +LL | type ETAI4 = impl Iterator<Item: Copy, Item: Send>; + | ^^^^^^^^^^ error: could not find defining uses + --> $DIR/duplicate.rs:129:28 + | +LL | type ETAI5 = impl Iterator<Item: Copy, Item: Copy>; + | ^^^^^^^^^^ error: could not find defining uses + --> $DIR/duplicate.rs:129:40 + | +LL | type ETAI5 = impl Iterator<Item: Copy, Item: Copy>; + | ^^^^^^^^^^ error: could not find defining uses + --> $DIR/duplicate.rs:134:28 + | +LL | type ETAI6 = impl Iterator<Item: 'static, Item: 'static>; + | ^^^^^^^^^^^^^ error: could not find defining uses + --> $DIR/duplicate.rs:134:43 + | +LL | type ETAI6 = impl Iterator<Item: 'static, Item: 'static>; + | ^^^^^^^^^^^^^ error: could not find defining uses + --> $DIR/duplicate.rs:171:28 + | +LL | type TADyn1 = dyn Iterator<Item: Copy, Item: Send>; + | ^^^^^^^^^^ error: could not find defining uses + --> $DIR/duplicate.rs:171:40 + | +LL | type TADyn1 = dyn Iterator<Item: Copy, Item: Send>; + | ^^^^^^^^^^ error: could not find defining uses + --> $DIR/duplicate.rs:175:32 + | +LL | type TADyn2 = Box<dyn Iterator<Item: Copy, Item: Copy>>; + | ^^^^^^^^^^ error: could not find defining uses + --> $DIR/duplicate.rs:175:44 + | +LL | type TADyn2 = Box<dyn Iterator<Item: Copy, Item: Copy>>; + | ^^^^^^^^^^ error: could not find defining uses + --> $DIR/duplicate.rs:179:28 + | +LL | type TADyn3 = dyn Iterator<Item: 'static, Item: 'static>; + | ^^^^^^^^^^^^^ error: could not find defining uses + --> $DIR/duplicate.rs:179:43 + | +LL | type TADyn3 = dyn Iterator<Item: 'static, Item: 'static>; + | ^^^^^^^^^^^^^ error: aborting due to 93 previous errors diff --git a/src/test/ui/associated-type-bounds/inside-adt.rs b/src/test/ui/associated-type-bounds/inside-adt.rs index 1257dc6e94b..83a60825d84 100644 --- a/src/test/ui/associated-type-bounds/inside-adt.rs +++ b/src/test/ui/associated-type-bounds/inside-adt.rs @@ -1,36 +1,33 @@ // compile-fail -// ignore-tidy-linelength -// error-pattern:could not find defining uses - #![feature(associated_type_bounds)] #![feature(untagged_unions)] struct S1 { f: dyn Iterator<Item: Copy> } -//~^ associated type bounds are not allowed within structs, enums, or unions -//~| the value of the associated type `Item` (from the trait `std::iter::Iterator`) must be specified [E0191] +//~^ ERROR associated type bounds are not allowed within structs, enums, or unions +//~| ERROR could not find defining uses struct S2 { f: Box<dyn Iterator<Item: Copy>> } -//~^ associated type bounds are not allowed within structs, enums, or unions -//~| the value of the associated type `Item` (from the trait `std::iter::Iterator`) must be specified [E0191] +//~^ ERROR associated type bounds are not allowed within structs, enums, or unions +//~| ERROR could not find defining uses struct S3 { f: dyn Iterator<Item: 'static> } -//~^ associated type bounds are not allowed within structs, enums, or unions -//~| the value of the associated type `Item` (from the trait `std::iter::Iterator`) must be specified [E0191] +//~^ ERROR associated type bounds are not allowed within structs, enums, or unions +//~| ERROR could not find defining uses enum E1 { V(dyn Iterator<Item: Copy>) } -//~^ associated type bounds are not allowed within structs, enums, or unions -//~| the value of the associated type `Item` (from the trait `std::iter::Iterator`) must be specified [E0191] +//~^ ERROR associated type bounds are not allowed within structs, enums, or unions +//~| ERROR could not find defining uses enum E2 { V(Box<dyn Iterator<Item: Copy>>) } -//~^ associated type bounds are not allowed within structs, enums, or unions -//~| the value of the associated type `Item` (from the trait `std::iter::Iterator`) must be specified [E0191] +//~^ ERROR associated type bounds are not allowed within structs, enums, or unions +//~| ERROR could not find defining uses enum E3 { V(dyn Iterator<Item: 'static>) } -//~^ associated type bounds are not allowed within structs, enums, or unions -//~| the value of the associated type `Item` (from the trait `std::iter::Iterator`) must be specified [E0191] +//~^ ERROR associated type bounds are not allowed within structs, enums, or unions +//~| ERROR could not find defining uses union U1 { f: dyn Iterator<Item: Copy> } -//~^ associated type bounds are not allowed within structs, enums, or unions -//~| the value of the associated type `Item` (from the trait `std::iter::Iterator`) must be specified [E0191] +//~^ ERROR associated type bounds are not allowed within structs, enums, or unions +//~| ERROR could not find defining uses union U2 { f: Box<dyn Iterator<Item: Copy>> } -//~^ associated type bounds are not allowed within structs, enums, or unions -//~| the value of the associated type `Item` (from the trait `std::iter::Iterator`) must be specified [E0191] +//~^ ERROR associated type bounds are not allowed within structs, enums, or unions +//~| ERROR could not find defining uses union U3 { f: dyn Iterator<Item: 'static> } -//~^ associated type bounds are not allowed within structs, enums, or unions -//~| the value of the associated type `Item` (from the trait `std::iter::Iterator`) must be specified [E0191] +//~^ ERROR associated type bounds are not allowed within structs, enums, or unions +//~| ERROR could not find defining uses diff --git a/src/test/ui/associated-type-bounds/inside-adt.stderr b/src/test/ui/associated-type-bounds/inside-adt.stderr index 7bdd71b8296..d0e0ceccd37 100644 --- a/src/test/ui/associated-type-bounds/inside-adt.stderr +++ b/src/test/ui/associated-type-bounds/inside-adt.stderr @@ -1,53 +1,53 @@ error: associated type bounds are not allowed within structs, enums, or unions - --> $DIR/inside-adt.rs:8:29 + --> $DIR/inside-adt.rs:5:29 | LL | struct S1 { f: dyn Iterator<Item: Copy> } | ^^^^^^^^^^ error: associated type bounds are not allowed within structs, enums, or unions - --> $DIR/inside-adt.rs:11:33 + --> $DIR/inside-adt.rs:8:33 | LL | struct S2 { f: Box<dyn Iterator<Item: Copy>> } | ^^^^^^^^^^ error: associated type bounds are not allowed within structs, enums, or unions - --> $DIR/inside-adt.rs:14:29 + --> $DIR/inside-adt.rs:11:29 | LL | struct S3 { f: dyn Iterator<Item: 'static> } | ^^^^^^^^^^^^^ error: associated type bounds are not allowed within structs, enums, or unions - --> $DIR/inside-adt.rs:18:26 + --> $DIR/inside-adt.rs:15:26 | LL | enum E1 { V(dyn Iterator<Item: Copy>) } | ^^^^^^^^^^ error: associated type bounds are not allowed within structs, enums, or unions - --> $DIR/inside-adt.rs:21:30 + --> $DIR/inside-adt.rs:18:30 | LL | enum E2 { V(Box<dyn Iterator<Item: Copy>>) } | ^^^^^^^^^^ error: associated type bounds are not allowed within structs, enums, or unions - --> $DIR/inside-adt.rs:24:26 + --> $DIR/inside-adt.rs:21:26 | LL | enum E3 { V(dyn Iterator<Item: 'static>) } | ^^^^^^^^^^^^^ error: associated type bounds are not allowed within structs, enums, or unions - --> $DIR/inside-adt.rs:28:28 + --> $DIR/inside-adt.rs:25:28 | LL | union U1 { f: dyn Iterator<Item: Copy> } | ^^^^^^^^^^ error: associated type bounds are not allowed within structs, enums, or unions - --> $DIR/inside-adt.rs:31:32 + --> $DIR/inside-adt.rs:28:32 | LL | union U2 { f: Box<dyn Iterator<Item: Copy>> } | ^^^^^^^^^^ error: associated type bounds are not allowed within structs, enums, or unions - --> $DIR/inside-adt.rs:34:28 + --> $DIR/inside-adt.rs:31:28 | LL | union U3 { f: dyn Iterator<Item: 'static> } | ^^^^^^^^^^^^^ @@ -57,22 +57,58 @@ error[E0601]: `main` function not found in crate `inside_adt` = note: consider adding a `main` function to `$DIR/inside-adt.rs` error: could not find defining uses + --> $DIR/inside-adt.rs:5:29 + | +LL | struct S1 { f: dyn Iterator<Item: Copy> } + | ^^^^^^^^^^ error: could not find defining uses + --> $DIR/inside-adt.rs:8:33 + | +LL | struct S2 { f: Box<dyn Iterator<Item: Copy>> } + | ^^^^^^^^^^ error: could not find defining uses + --> $DIR/inside-adt.rs:11:29 + | +LL | struct S3 { f: dyn Iterator<Item: 'static> } + | ^^^^^^^^^^^^^ error: could not find defining uses + --> $DIR/inside-adt.rs:15:26 + | +LL | enum E1 { V(dyn Iterator<Item: Copy>) } + | ^^^^^^^^^^ error: could not find defining uses + --> $DIR/inside-adt.rs:18:30 + | +LL | enum E2 { V(Box<dyn Iterator<Item: Copy>>) } + | ^^^^^^^^^^ error: could not find defining uses + --> $DIR/inside-adt.rs:21:26 + | +LL | enum E3 { V(dyn Iterator<Item: 'static>) } + | ^^^^^^^^^^^^^ error: could not find defining uses + --> $DIR/inside-adt.rs:25:28 + | +LL | union U1 { f: dyn Iterator<Item: Copy> } + | ^^^^^^^^^^ error: could not find defining uses + --> $DIR/inside-adt.rs:28:32 + | +LL | union U2 { f: Box<dyn Iterator<Item: Copy>> } + | ^^^^^^^^^^ error: could not find defining uses + --> $DIR/inside-adt.rs:31:28 + | +LL | union U3 { f: dyn Iterator<Item: 'static> } + | ^^^^^^^^^^^^^ error: aborting due to 19 previous errors diff --git a/src/test/ui/associated-type/associated-type-projection-from-supertrait.rs b/src/test/ui/associated-type/associated-type-projection-from-supertrait.rs index 06dfe490b8b..7e05bcd309a 100644 --- a/src/test/ui/associated-type/associated-type-projection-from-supertrait.rs +++ b/src/test/ui/associated-type/associated-type-projection-from-supertrait.rs @@ -12,30 +12,22 @@ pub trait Car : Vehicle { fn chip_paint(&self, c: Self::Color) { } } -/////////////////////////////////////////////////////////////////////////// - struct Black; struct ModelT; impl Vehicle for ModelT { type Color = Black; } impl Car for ModelT { } -/////////////////////////////////////////////////////////////////////////// - struct Blue; struct ModelU; impl Vehicle for ModelU { type Color = Blue; } impl Car for ModelU { } -/////////////////////////////////////////////////////////////////////////// - fn dent<C:Car>(c: C, color: C::Color) { c.chip_paint(color) } fn a() { dent(ModelT, Black); } fn b() { dent(ModelT, Blue); } //~ ERROR mismatched types fn c() { dent(ModelU, Black); } //~ ERROR mismatched types fn d() { dent(ModelU, Blue); } -/////////////////////////////////////////////////////////////////////////// - fn e() { ModelT.chip_paint(Black); } fn f() { ModelT.chip_paint(Blue); } //~ ERROR mismatched types fn g() { ModelU.chip_paint(Black); } //~ ERROR mismatched types diff --git a/src/test/ui/associated-type/associated-type-projection-from-supertrait.stderr b/src/test/ui/associated-type/associated-type-projection-from-supertrait.stderr index 06f1a1cc64c..4ba4925ef1b 100644 --- a/src/test/ui/associated-type/associated-type-projection-from-supertrait.stderr +++ b/src/test/ui/associated-type/associated-type-projection-from-supertrait.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/associated-type-projection-from-supertrait.rs:33:23 + --> $DIR/associated-type-projection-from-supertrait.rs:27:23 | LL | fn b() { dent(ModelT, Blue); } | ^^^^ expected struct `Black`, found struct `Blue` @@ -8,7 +8,7 @@ LL | fn b() { dent(ModelT, Blue); } found type `Blue` error[E0308]: mismatched types - --> $DIR/associated-type-projection-from-supertrait.rs:34:23 + --> $DIR/associated-type-projection-from-supertrait.rs:28:23 | LL | fn c() { dent(ModelU, Black); } | ^^^^^ expected struct `Blue`, found struct `Black` @@ -17,7 +17,7 @@ LL | fn c() { dent(ModelU, Black); } found type `Black` error[E0308]: mismatched types - --> $DIR/associated-type-projection-from-supertrait.rs:40:28 + --> $DIR/associated-type-projection-from-supertrait.rs:32:28 | LL | fn f() { ModelT.chip_paint(Blue); } | ^^^^ expected struct `Black`, found struct `Blue` @@ -26,7 +26,7 @@ LL | fn f() { ModelT.chip_paint(Blue); } found type `Blue` error[E0308]: mismatched types - --> $DIR/associated-type-projection-from-supertrait.rs:41:28 + --> $DIR/associated-type-projection-from-supertrait.rs:33:28 | LL | fn g() { ModelU.chip_paint(Black); } | ^^^^^ expected struct `Blue`, found struct `Black` diff --git a/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.rs b/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.rs index 653130843c8..6b2bbbe2e4f 100644 --- a/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.rs +++ b/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.rs @@ -11,22 +11,16 @@ pub trait Car : Vehicle { fn honk(&self) { } } -/////////////////////////////////////////////////////////////////////////// - struct Black; struct ModelT; impl Vehicle for ModelT { type Color = Black; } impl Car for ModelT { } -/////////////////////////////////////////////////////////////////////////// - struct Blue; struct ModelU; impl Vehicle for ModelU { type Color = Blue; } impl Car for ModelU { } -/////////////////////////////////////////////////////////////////////////// - fn black_car<C:Car<Color=Black>>(c: C) { } diff --git a/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.stderr b/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.stderr index 4b548604983..89c48d50cdb 100644 --- a/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.stderr +++ b/src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.stderr @@ -1,5 +1,5 @@ error[E0271]: type mismatch resolving `<ModelT as Vehicle>::Color == Blue` - --> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:37:10 + --> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:31:10 | LL | fn b() { blue_car(ModelT); } | ^^^^^^^^ expected struct `Black`, found struct `Blue` @@ -7,13 +7,13 @@ LL | fn b() { blue_car(ModelT); } = note: expected type `Black` found type `Blue` note: required by `blue_car` - --> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:33:1 + --> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:27:1 | LL | fn blue_car<C:Car<Color=Blue>>(c: C) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0271]: type mismatch resolving `<ModelU as Vehicle>::Color == Black` - --> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:38:10 + --> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:32:10 | LL | fn c() { black_car(ModelU); } | ^^^^^^^^^ expected struct `Blue`, found struct `Black` @@ -21,7 +21,7 @@ LL | fn c() { black_car(ModelU); } = note: expected type `Blue` found type `Black` note: required by `black_car` - --> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:30:1 + --> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:24:1 | LL | fn black_car<C:Car<Color=Black>>(c: C) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/associated-types/associated-types-ref-from-struct.rs b/src/test/ui/associated-types/associated-types-ref-from-struct.rs index 3ccba289e4b..c89f6046e6b 100644 --- a/src/test/ui/associated-types/associated-types-ref-from-struct.rs +++ b/src/test/ui/associated-types/associated-types-ref-from-struct.rs @@ -9,8 +9,6 @@ trait Test { fn test(&self, value: &Self::V) -> bool; } -/////////////////////////////////////////////////////////////////////////// - struct TesterPair<T:Test> { tester: T, value: T::V, @@ -26,8 +24,6 @@ impl<T:Test> TesterPair<T> { } } -/////////////////////////////////////////////////////////////////////////// - struct EqU32(u32); impl Test for EqU32 { type V = u32; diff --git a/src/test/ui/async-await/argument-patterns.rs b/src/test/ui/async-await/argument-patterns.rs index 3750c2bcb70..0e42f48b835 100644 --- a/src/test/ui/async-await/argument-patterns.rs +++ b/src/test/ui/async-await/argument-patterns.rs @@ -3,7 +3,6 @@ #![allow(unused_variables)] #![deny(unused_mut)] -#![feature(async_await)] type A = Vec<u32>; diff --git a/src/test/ui/async-await/async-await.rs b/src/test/ui/async-await/async-await.rs index 8a15eb8c573..bf8bf0bcce0 100644 --- a/src/test/ui/async-await/async-await.rs +++ b/src/test/ui/async-await/async-await.rs @@ -3,8 +3,6 @@ // edition:2018 // aux-build:arc_wake.rs -#![feature(async_await)] - extern crate arc_wake; use std::pin::Pin; diff --git a/src/test/ui/async-await/async-block-control-flow-static-semantics.rs b/src/test/ui/async-await/async-block-control-flow-static-semantics.rs index 6a766ede0ed..90d75118f8e 100644 --- a/src/test/ui/async-await/async-block-control-flow-static-semantics.rs +++ b/src/test/ui/async-await/async-block-control-flow-static-semantics.rs @@ -6,8 +6,6 @@ // edition:2018 // ignore-tidy-linelength -#![feature(async_await)] - fn main() {} use core::future::Future; @@ -32,15 +30,14 @@ async fn return_targets_async_block_not_async_fn() -> u8 { fn no_break_in_async_block() { async { - break 0u8; //~ ERROR `break` inside of a closure - // FIXME: This diagnostic is pretty bad. + break 0u8; //~ ERROR `break` inside of an async block }; } fn no_break_in_async_block_even_with_outer_loop() { loop { async { - break 0u8; //~ ERROR `break` inside of a closure + break 0u8; //~ ERROR `break` inside of an async block }; } } diff --git a/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr b/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr index f3f2d14584e..bc42a46ae10 100644 --- a/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr +++ b/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr @@ -1,17 +1,17 @@ -error[E0267]: `break` inside of a closure - --> $DIR/async-block-control-flow-static-semantics.rs:35:9 +error[E0267]: `break` inside of an async block + --> $DIR/async-block-control-flow-static-semantics.rs:33:9 | LL | break 0u8; - | ^^^^^^^^^ cannot break inside of a closure + | ^^^^^^^^^ cannot break inside of an async block -error[E0267]: `break` inside of a closure - --> $DIR/async-block-control-flow-static-semantics.rs:43:13 +error[E0267]: `break` inside of an async block + --> $DIR/async-block-control-flow-static-semantics.rs:40:13 | LL | break 0u8; - | ^^^^^^^^^ cannot break inside of a closure + | ^^^^^^^^^ cannot break inside of an async block error[E0308]: mismatched types - --> $DIR/async-block-control-flow-static-semantics.rs:15:43 + --> $DIR/async-block-control-flow-static-semantics.rs:13:43 | LL | fn return_targets_async_block_not_fn() -> u8 { | --------------------------------- ^^ expected u8, found () @@ -22,7 +22,7 @@ LL | fn return_targets_async_block_not_fn() -> u8 { found type `()` error[E0271]: type mismatch resolving `<impl std::future::Future as std::future::Future>::Output == ()` - --> $DIR/async-block-control-flow-static-semantics.rs:20:39 + --> $DIR/async-block-control-flow-static-semantics.rs:18:39 | LL | let _: &dyn Future<Output = ()> = █ | ^^^^^^ expected u8, found () @@ -32,7 +32,7 @@ LL | let _: &dyn Future<Output = ()> = █ = note: required for the cast to the object type `dyn std::future::Future<Output = ()>` error[E0271]: type mismatch resolving `<impl std::future::Future as std::future::Future>::Output == ()` - --> $DIR/async-block-control-flow-static-semantics.rs:29:39 + --> $DIR/async-block-control-flow-static-semantics.rs:27:39 | LL | let _: &dyn Future<Output = ()> = █ | ^^^^^^ expected u8, found () @@ -42,7 +42,7 @@ LL | let _: &dyn Future<Output = ()> = █ = note: required for the cast to the object type `dyn std::future::Future<Output = ()>` error[E0271]: type mismatch resolving `<impl std::future::Future as std::future::Future>::Output == u8` - --> $DIR/async-block-control-flow-static-semantics.rs:24:55 + --> $DIR/async-block-control-flow-static-semantics.rs:22:55 | LL | async fn return_targets_async_block_not_async_fn() -> u8 { | ^^ expected (), found u8 @@ -52,7 +52,7 @@ LL | async fn return_targets_async_block_not_async_fn() -> u8 { = note: the return type of a function must have a statically known size error[E0308]: mismatched types - --> $DIR/async-block-control-flow-static-semantics.rs:51:44 + --> $DIR/async-block-control-flow-static-semantics.rs:48:44 | LL | fn rethrow_targets_async_block_not_fn() -> Result<u8, MyErr> { | ---------------------------------- ^^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found () @@ -63,7 +63,7 @@ LL | fn rethrow_targets_async_block_not_fn() -> Result<u8, MyErr> { found type `()` error[E0308]: mismatched types - --> $DIR/async-block-control-flow-static-semantics.rs:60:50 + --> $DIR/async-block-control-flow-static-semantics.rs:57:50 | LL | fn rethrow_targets_async_block_not_async_fn() -> Result<u8, MyErr> { | ---------------------------------------- ^^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found () diff --git a/src/test/ui/async-await/async-borrowck-escaping-closure-error.rs b/src/test/ui/async-await/async-borrowck-escaping-closure-error.rs new file mode 100644 index 00000000000..d2fa5d0a3d0 --- /dev/null +++ b/src/test/ui/async-await/async-borrowck-escaping-closure-error.rs @@ -0,0 +1,10 @@ +// edition:2018 +#![feature(async_closure,async_await)] +fn foo() -> Box<dyn std::future::Future<Output = u32>> { + let x = 0u32; + Box::new((async || x)()) + //~^ ERROR E0373 +} + +fn main() { +} diff --git a/src/test/ui/async-await/async-borrowck-escaping-closure-error.stderr b/src/test/ui/async-await/async-borrowck-escaping-closure-error.stderr new file mode 100644 index 00000000000..8bcfcf98920 --- /dev/null +++ b/src/test/ui/async-await/async-borrowck-escaping-closure-error.stderr @@ -0,0 +1,21 @@ +error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function + --> $DIR/async-borrowck-escaping-closure-error.rs:5:15 + | +LL | Box::new((async || x)()) + | ^^^^^^^^ - `x` is borrowed here + | | + | may outlive borrowed value `x` + | +note: closure is returned here + --> $DIR/async-borrowck-escaping-closure-error.rs:5:5 + | +LL | Box::new((async || x)()) + | ^^^^^^^^^^^^^^^^^^^^^^^^ +help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword + | +LL | Box::new((async move || x)()) + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0373`. diff --git a/src/test/ui/async-await/async-closure-matches-expr.rs b/src/test/ui/async-await/async-closure-matches-expr.rs index 1c192a4d1d8..d82fbcdc550 100644 --- a/src/test/ui/async-await/async-closure-matches-expr.rs +++ b/src/test/ui/async-await/async-closure-matches-expr.rs @@ -1,7 +1,7 @@ // build-pass // edition:2018 -#![feature(async_await, async_closure)] +#![feature(async_closure)] macro_rules! match_expr { ($x:expr) => {} diff --git a/src/test/ui/async-await/async-closure.rs b/src/test/ui/async-await/async-closure.rs index 925b54b3985..9a24bd8c954 100644 --- a/src/test/ui/async-await/async-closure.rs +++ b/src/test/ui/async-await/async-closure.rs @@ -3,7 +3,7 @@ // edition:2018 // aux-build:arc_wake.rs -#![feature(async_await, async_closure)] +#![feature(async_closure)] extern crate arc_wake; diff --git a/src/test/ui/async-await/async-error-span.rs b/src/test/ui/async-await/async-error-span.rs index d362348a3fd..dec3ac0f685 100644 --- a/src/test/ui/async-await/async-error-span.rs +++ b/src/test/ui/async-await/async-error-span.rs @@ -1,7 +1,6 @@ // edition:2018 -#![feature(async_await)] -// Regression test for issue #62382 +// Regression test for issue #62382. use std::future::Future; diff --git a/src/test/ui/async-await/async-error-span.stderr b/src/test/ui/async-await/async-error-span.stderr index bd8966b9c7d..47441f5e4ef 100644 --- a/src/test/ui/async-await/async-error-span.stderr +++ b/src/test/ui/async-await/async-error-span.stderr @@ -1,11 +1,11 @@ error[E0698]: type inside `async` object must be known in this context - --> $DIR/async-error-span.rs:13:9 + --> $DIR/async-error-span.rs:12:9 | LL | let a; | ^ cannot infer type | note: the type is part of the `async` object because of this `await` - --> $DIR/async-error-span.rs:14:5 + --> $DIR/async-error-span.rs:13:5 | LL | get_future().await; | ^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/async-await/async-fn-elided-impl-lifetime-parameter.rs b/src/test/ui/async-await/async-fn-elided-impl-lifetime-parameter.rs new file mode 100644 index 00000000000..1c369fd7415 --- /dev/null +++ b/src/test/ui/async-await/async-fn-elided-impl-lifetime-parameter.rs @@ -0,0 +1,15 @@ +// Check that `async fn` inside of an impl with `'_` +// in the header compiles correctly. +// +// Regression test for #63500. +// +// check-pass +// edition:2018 + +struct Foo<'a>(&'a u8); + +impl Foo<'_> { + async fn bar() {} +} + +fn main() { } diff --git a/src/test/ui/async-await/async-fn-nonsend.rs b/src/test/ui/async-await/async-fn-nonsend.rs index 612c1e29d82..1f1bf4250ea 100644 --- a/src/test/ui/async-await/async-fn-nonsend.rs +++ b/src/test/ui/async-await/async-fn-nonsend.rs @@ -2,8 +2,6 @@ // edition:2018 // compile-flags: --crate-type lib -#![feature(async_await)] - use std::{ cell::RefCell, fmt::Debug, diff --git a/src/test/ui/async-await/async-fn-nonsend.stderr b/src/test/ui/async-await/async-fn-nonsend.stderr index 7776a36a28f..6b4fff2dc68 100644 --- a/src/test/ui/async-await/async-fn-nonsend.stderr +++ b/src/test/ui/async-await/async-fn-nonsend.stderr @@ -1,5 +1,5 @@ error[E0277]: `std::rc::Rc<()>` cannot be sent between threads safely - --> $DIR/async-fn-nonsend.rs:52:5 + --> $DIR/async-fn-nonsend.rs:50:5 | LL | assert_send(local_dropped_before_await()); | ^^^^^^^^^^^ `std::rc::Rc<()>` cannot be sent between threads safely @@ -7,18 +7,18 @@ LL | assert_send(local_dropped_before_await()); = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<()>` = note: required because it appears within the type `impl std::fmt::Debug` = note: required because it appears within the type `{impl std::fmt::Debug, impl std::future::Future, ()}` - = note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:23:39: 28:2 {impl std::fmt::Debug, impl std::future::Future, ()}]` - = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:23:39: 28:2 {impl std::fmt::Debug, impl std::future::Future, ()}]>` + = note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:21:39: 26:2 {impl std::fmt::Debug, impl std::future::Future, ()}]` + = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:21:39: 26:2 {impl std::fmt::Debug, impl std::future::Future, ()}]>` = note: required because it appears within the type `impl std::future::Future` = note: required because it appears within the type `impl std::future::Future` note: required by `assert_send` - --> $DIR/async-fn-nonsend.rs:49:1 + --> $DIR/async-fn-nonsend.rs:47:1 | LL | fn assert_send(_: impl Send) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `std::rc::Rc<()>` cannot be sent between threads safely - --> $DIR/async-fn-nonsend.rs:54:5 + --> $DIR/async-fn-nonsend.rs:52:5 | LL | assert_send(non_send_temporary_in_match()); | ^^^^^^^^^^^ `std::rc::Rc<()>` cannot be sent between threads safely @@ -26,18 +26,18 @@ LL | assert_send(non_send_temporary_in_match()); = help: within `impl std::future::Future`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<()>` = note: required because it appears within the type `impl std::fmt::Debug` = note: required because it appears within the type `{fn(impl std::fmt::Debug) -> std::option::Option<impl std::fmt::Debug> {std::option::Option::<impl std::fmt::Debug>::Some}, fn() -> impl std::fmt::Debug {non_send}, impl std::fmt::Debug, std::option::Option<impl std::fmt::Debug>, impl std::future::Future, ()}` - = note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:30:40: 39:2 {fn(impl std::fmt::Debug) -> std::option::Option<impl std::fmt::Debug> {std::option::Option::<impl std::fmt::Debug>::Some}, fn() -> impl std::fmt::Debug {non_send}, impl std::fmt::Debug, std::option::Option<impl std::fmt::Debug>, impl std::future::Future, ()}]` - = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:30:40: 39:2 {fn(impl std::fmt::Debug) -> std::option::Option<impl std::fmt::Debug> {std::option::Option::<impl std::fmt::Debug>::Some}, fn() -> impl std::fmt::Debug {non_send}, impl std::fmt::Debug, std::option::Option<impl std::fmt::Debug>, impl std::future::Future, ()}]>` + = note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:28:40: 37:2 {fn(impl std::fmt::Debug) -> std::option::Option<impl std::fmt::Debug> {std::option::Option::<impl std::fmt::Debug>::Some}, fn() -> impl std::fmt::Debug {non_send}, impl std::fmt::Debug, std::option::Option<impl std::fmt::Debug>, impl std::future::Future, ()}]` + = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:28:40: 37:2 {fn(impl std::fmt::Debug) -> std::option::Option<impl std::fmt::Debug> {std::option::Option::<impl std::fmt::Debug>::Some}, fn() -> impl std::fmt::Debug {non_send}, impl std::fmt::Debug, std::option::Option<impl std::fmt::Debug>, impl std::future::Future, ()}]>` = note: required because it appears within the type `impl std::future::Future` = note: required because it appears within the type `impl std::future::Future` note: required by `assert_send` - --> $DIR/async-fn-nonsend.rs:49:1 + --> $DIR/async-fn-nonsend.rs:47:1 | LL | fn assert_send(_: impl Send) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `dyn std::fmt::Write` cannot be sent between threads safely - --> $DIR/async-fn-nonsend.rs:56:5 + --> $DIR/async-fn-nonsend.rs:54:5 | LL | assert_send(non_sync_with_method_call()); | ^^^^^^^^^^^ `dyn std::fmt::Write` cannot be sent between threads safely @@ -47,18 +47,18 @@ LL | assert_send(non_sync_with_method_call()); = note: required because it appears within the type `std::fmt::Formatter<'_>` = note: required because of the requirements on the impl of `std::marker::Send` for `&mut std::fmt::Formatter<'_>` = note: required because it appears within the type `for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}` - = note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:41:38: 47:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}]` - = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:41:38: 47:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}]>` + = note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:39:38: 45:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}]` + = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:39:38: 45:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}]>` = note: required because it appears within the type `impl std::future::Future` = note: required because it appears within the type `impl std::future::Future` note: required by `assert_send` - --> $DIR/async-fn-nonsend.rs:49:1 + --> $DIR/async-fn-nonsend.rs:47:1 | LL | fn assert_send(_: impl Send) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely - --> $DIR/async-fn-nonsend.rs:56:5 + --> $DIR/async-fn-nonsend.rs:54:5 | LL | assert_send(non_sync_with_method_call()); | ^^^^^^^^^^^ `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely @@ -72,12 +72,12 @@ LL | assert_send(non_sync_with_method_call()); = note: required because it appears within the type `std::fmt::Formatter<'_>` = note: required because of the requirements on the impl of `std::marker::Send` for `&mut std::fmt::Formatter<'_>` = note: required because it appears within the type `for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}` - = note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:41:38: 47:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}]` - = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:41:38: 47:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}]>` + = note: required because it appears within the type `[static generator@$DIR/async-fn-nonsend.rs:39:38: 45:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}]` + = note: required because it appears within the type `std::future::GenFuture<[static generator@$DIR/async-fn-nonsend.rs:39:38: 45:2 for<'r, 's> {&'r mut std::fmt::Formatter<'s>, bool, impl std::future::Future, ()}]>` = note: required because it appears within the type `impl std::future::Future` = note: required because it appears within the type `impl std::future::Future` note: required by `assert_send` - --> $DIR/async-fn-nonsend.rs:49:1 + --> $DIR/async-fn-nonsend.rs:47:1 | LL | fn assert_send(_: impl Send) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/async-await/async-fn-path-elision.rs b/src/test/ui/async-await/async-fn-path-elision.rs index 447e40dddd9..3f1f51c20ca 100644 --- a/src/test/ui/async-await/async-fn-path-elision.rs +++ b/src/test/ui/async-await/async-fn-path-elision.rs @@ -1,8 +1,5 @@ // edition:2018 -#![feature(async_await)] -#![allow(dead_code)] - struct HasLifetime<'a>(&'a bool); async fn error(lt: HasLifetime) { //~ ERROR implicit elided lifetime not allowed here diff --git a/src/test/ui/async-await/async-fn-path-elision.stderr b/src/test/ui/async-await/async-fn-path-elision.stderr index 3b311baba01..9694742200e 100644 --- a/src/test/ui/async-await/async-fn-path-elision.stderr +++ b/src/test/ui/async-await/async-fn-path-elision.stderr @@ -1,5 +1,5 @@ error[E0726]: implicit elided lifetime not allowed here - --> $DIR/async-fn-path-elision.rs:8:20 + --> $DIR/async-fn-path-elision.rs:5:20 | LL | async fn error(lt: HasLifetime) { | ^^^^^^^^^^^- help: indicate the anonymous lifetime: `<'_>` diff --git a/src/test/ui/async-await/async-fn-send-uses-nonsend.rs b/src/test/ui/async-await/async-fn-send-uses-nonsend.rs index 5e1b8c6280b..35d9cb15540 100644 --- a/src/test/ui/async-await/async-fn-send-uses-nonsend.rs +++ b/src/test/ui/async-await/async-fn-send-uses-nonsend.rs @@ -2,8 +2,6 @@ // edition:2018 // compile-flags: --crate-type lib -#![feature(async_await)] - use std::{ cell::RefCell, fmt::Debug, diff --git a/src/test/ui/async-await/async-fn-size-moved-locals.rs b/src/test/ui/async-await/async-fn-size-moved-locals.rs index 30b59d037d5..3ffcbb58595 100644 --- a/src/test/ui/async-await/async-fn-size-moved-locals.rs +++ b/src/test/ui/async-await/async-fn-size-moved-locals.rs @@ -12,8 +12,6 @@ // edition:2018 -#![feature(async_await)] - use std::future::Future; use std::pin::Pin; use std::task::{Context, Poll}; diff --git a/src/test/ui/async-await/async-fn-size.rs b/src/test/ui/async-await/async-fn-size.rs index c6b2ed13b0a..b5c94ecb716 100644 --- a/src/test/ui/async-await/async-fn-size.rs +++ b/src/test/ui/async-await/async-fn-size.rs @@ -2,8 +2,6 @@ // aux-build:arc_wake.rs // edition:2018 -#![feature(async_await)] - extern crate arc_wake; use std::pin::Pin; diff --git a/src/test/ui/async-await/async-matches-expr.rs b/src/test/ui/async-await/async-matches-expr.rs index a6f0211e41f..299faa0587b 100644 --- a/src/test/ui/async-await/async-matches-expr.rs +++ b/src/test/ui/async-await/async-matches-expr.rs @@ -1,8 +1,6 @@ // build-pass (FIXME(62277): could be check-pass?) // edition:2018 -#![feature(async_await)] - macro_rules! match_expr { ($x:expr) => {} } diff --git a/src/test/ui/async-await/async-unsafe-fn-call-in-safe.rs b/src/test/ui/async-await/async-unsafe-fn-call-in-safe.rs index cb9156dcc6e..ccc1b8553f0 100644 --- a/src/test/ui/async-await/async-unsafe-fn-call-in-safe.rs +++ b/src/test/ui/async-await/async-unsafe-fn-call-in-safe.rs @@ -1,7 +1,5 @@ // edition:2018 -#![feature(async_await)] - struct S; impl S { diff --git a/src/test/ui/async-await/async-unsafe-fn-call-in-safe.stderr b/src/test/ui/async-await/async-unsafe-fn-call-in-safe.stderr index d22413beecb..c95fe173488 100644 --- a/src/test/ui/async-await/async-unsafe-fn-call-in-safe.stderr +++ b/src/test/ui/async-await/async-unsafe-fn-call-in-safe.stderr @@ -1,5 +1,5 @@ error[E0133]: call to unsafe function is unsafe and requires unsafe function or block - --> $DIR/async-unsafe-fn-call-in-safe.rs:14:5 + --> $DIR/async-unsafe-fn-call-in-safe.rs:12:5 | LL | S::f(); | ^^^^^^ call to unsafe function @@ -7,7 +7,7 @@ LL | S::f(); = note: consult the function's documentation for information on how to avoid undefined behavior error[E0133]: call to unsafe function is unsafe and requires unsafe function or block - --> $DIR/async-unsafe-fn-call-in-safe.rs:15:5 + --> $DIR/async-unsafe-fn-call-in-safe.rs:13:5 | LL | f(); | ^^^ call to unsafe function @@ -15,7 +15,7 @@ LL | f(); = note: consult the function's documentation for information on how to avoid undefined behavior error[E0133]: call to unsafe function is unsafe and requires unsafe function or block - --> $DIR/async-unsafe-fn-call-in-safe.rs:19:5 + --> $DIR/async-unsafe-fn-call-in-safe.rs:17:5 | LL | S::f(); | ^^^^^^ call to unsafe function @@ -23,7 +23,7 @@ LL | S::f(); = note: consult the function's documentation for information on how to avoid undefined behavior error[E0133]: call to unsafe function is unsafe and requires unsafe function or block - --> $DIR/async-unsafe-fn-call-in-safe.rs:20:5 + --> $DIR/async-unsafe-fn-call-in-safe.rs:18:5 | LL | f(); | ^^^ call to unsafe function diff --git a/src/test/ui/async-await/async-with-closure.rs b/src/test/ui/async-await/async-with-closure.rs index f7dc874affd..0b225526675 100644 --- a/src/test/ui/async-await/async-with-closure.rs +++ b/src/test/ui/async-await/async-with-closure.rs @@ -1,8 +1,6 @@ // build-pass (FIXME(62277): could be check-pass?) // edition:2018 -#![feature(async_await)] - trait MyClosure { type Args; } diff --git a/src/test/ui/async-await/await-keyword/2015-edition-error-various-positions.rs b/src/test/ui/async-await/await-keyword/2015-edition-error-various-positions.rs index 422a5a6394f..a3a20cb97e1 100644 --- a/src/test/ui/async-await/await-keyword/2015-edition-error-various-positions.rs +++ b/src/test/ui/async-await/await-keyword/2015-edition-error-various-positions.rs @@ -1,4 +1,3 @@ -#![feature(async_await)] #![allow(non_camel_case_types)] #![deny(keyword_idents)] diff --git a/src/test/ui/async-await/await-keyword/2015-edition-error-various-positions.stderr b/src/test/ui/async-await/await-keyword/2015-edition-error-various-positions.stderr index 8af0110169e..f1a22cda51b 100644 --- a/src/test/ui/async-await/await-keyword/2015-edition-error-various-positions.stderr +++ b/src/test/ui/async-await/await-keyword/2015-edition-error-various-positions.stderr @@ -1,11 +1,11 @@ error: `await` is a keyword in the 2018 edition - --> $DIR/2015-edition-error-various-positions.rs:6:13 + --> $DIR/2015-edition-error-various-positions.rs:5:13 | LL | pub mod await { | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` | note: lint level defined here - --> $DIR/2015-edition-error-various-positions.rs:3:9 + --> $DIR/2015-edition-error-various-positions.rs:2:9 | LL | #![deny(keyword_idents)] | ^^^^^^^^^^^^^^ @@ -13,7 +13,7 @@ LL | #![deny(keyword_idents)] = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716> error: `await` is a keyword in the 2018 edition - --> $DIR/2015-edition-error-various-positions.rs:8:20 + --> $DIR/2015-edition-error-various-positions.rs:7:20 | LL | pub struct await; | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` @@ -22,7 +22,7 @@ LL | pub struct await; = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716> error: `await` is a keyword in the 2018 edition - --> $DIR/2015-edition-error-various-positions.rs:12:16 + --> $DIR/2015-edition-error-various-positions.rs:11:16 | LL | use outer_mod::await::await; | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` @@ -31,7 +31,7 @@ LL | use outer_mod::await::await; = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716> error: `await` is a keyword in the 2018 edition - --> $DIR/2015-edition-error-various-positions.rs:12:23 + --> $DIR/2015-edition-error-various-positions.rs:11:23 | LL | use outer_mod::await::await; | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` @@ -40,7 +40,7 @@ LL | use outer_mod::await::await; = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716> error: `await` is a keyword in the 2018 edition - --> $DIR/2015-edition-error-various-positions.rs:17:14 + --> $DIR/2015-edition-error-various-positions.rs:16:14 | LL | struct Foo { await: () } | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` @@ -49,7 +49,7 @@ LL | struct Foo { await: () } = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716> error: `await` is a keyword in the 2018 edition - --> $DIR/2015-edition-error-various-positions.rs:21:15 + --> $DIR/2015-edition-error-various-positions.rs:20:15 | LL | impl Foo { fn await() {} } | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` @@ -58,7 +58,7 @@ LL | impl Foo { fn await() {} } = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716> error: `await` is a keyword in the 2018 edition - --> $DIR/2015-edition-error-various-positions.rs:25:14 + --> $DIR/2015-edition-error-various-positions.rs:24:14 | LL | macro_rules! await { | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` @@ -67,7 +67,7 @@ LL | macro_rules! await { = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716> error: `await` is a keyword in the 2018 edition - --> $DIR/2015-edition-error-various-positions.rs:32:5 + --> $DIR/2015-edition-error-various-positions.rs:31:5 | LL | await!(); | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` @@ -76,7 +76,7 @@ LL | await!(); = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716> error: `await` is a keyword in the 2018 edition - --> $DIR/2015-edition-error-various-positions.rs:35:11 + --> $DIR/2015-edition-error-various-positions.rs:34:11 | LL | match await { await => {} } | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` @@ -85,7 +85,7 @@ LL | match await { await => {} } = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716> error: `await` is a keyword in the 2018 edition - --> $DIR/2015-edition-error-various-positions.rs:35:19 + --> $DIR/2015-edition-error-various-positions.rs:34:19 | LL | match await { await => {} } | ^^^^^ help: you can use a raw identifier to stay compatible: `r#await` diff --git a/src/test/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.rs b/src/test/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.rs index 92f3210ac89..5d85b0a243e 100644 --- a/src/test/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.rs +++ b/src/test/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.rs @@ -1,7 +1,6 @@ // edition:2018 #![allow(non_camel_case_types)] -#![feature(async_await)] mod outer_mod { pub mod await { //~ ERROR expected identifier, found reserved keyword `await` diff --git a/src/test/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.stderr b/src/test/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.stderr index c4b82b29f02..05f28d0a5b2 100644 --- a/src/test/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.stderr +++ b/src/test/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.stderr @@ -1,5 +1,5 @@ error: expected identifier, found reserved keyword `await` - --> $DIR/2018-edition-error-in-non-macro-position.rs:7:13 + --> $DIR/2018-edition-error-in-non-macro-position.rs:6:13 | LL | pub mod await { | ^^^^^ expected identifier, found reserved keyword @@ -9,7 +9,7 @@ LL | pub mod r#await { | ^^^^^^^ error: expected identifier, found reserved keyword `await` - --> $DIR/2018-edition-error-in-non-macro-position.rs:8:20 + --> $DIR/2018-edition-error-in-non-macro-position.rs:7:20 | LL | pub struct await; | ^^^^^ expected identifier, found reserved keyword @@ -19,7 +19,7 @@ LL | pub struct r#await; | ^^^^^^^ error: expected identifier, found reserved keyword `await` - --> $DIR/2018-edition-error-in-non-macro-position.rs:11:22 + --> $DIR/2018-edition-error-in-non-macro-position.rs:10:22 | LL | use self::outer_mod::await::await; | ^^^^^ expected identifier, found reserved keyword @@ -29,7 +29,7 @@ LL | use self::outer_mod::r#await::await; | ^^^^^^^ error: expected identifier, found reserved keyword `await` - --> $DIR/2018-edition-error-in-non-macro-position.rs:11:29 + --> $DIR/2018-edition-error-in-non-macro-position.rs:10:29 | LL | use self::outer_mod::await::await; | ^^^^^ expected identifier, found reserved keyword @@ -39,7 +39,7 @@ LL | use self::outer_mod::await::r#await; | ^^^^^^^ error: expected identifier, found reserved keyword `await` - --> $DIR/2018-edition-error-in-non-macro-position.rs:14:14 + --> $DIR/2018-edition-error-in-non-macro-position.rs:13:14 | LL | struct Foo { await: () } | ^^^^^ expected identifier, found reserved keyword @@ -49,7 +49,7 @@ LL | struct Foo { r#await: () } | ^^^^^^^ error: expected identifier, found reserved keyword `await` - --> $DIR/2018-edition-error-in-non-macro-position.rs:17:15 + --> $DIR/2018-edition-error-in-non-macro-position.rs:16:15 | LL | impl Foo { fn await() {} } | ^^^^^ expected identifier, found reserved keyword @@ -59,7 +59,7 @@ LL | impl Foo { fn r#await() {} } | ^^^^^^^ error: expected identifier, found reserved keyword `await` - --> $DIR/2018-edition-error-in-non-macro-position.rs:20:14 + --> $DIR/2018-edition-error-in-non-macro-position.rs:19:14 | LL | macro_rules! await { | ^^^^^ expected identifier, found reserved keyword diff --git a/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.rs b/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.rs index 25da337c587..22bcbb1064d 100644 --- a/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.rs +++ b/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.rs @@ -1,7 +1,5 @@ // edition:2018 -#![feature(async_await)] - async fn bar() -> Result<(), ()> { Ok(()) } 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 db86d3d5d03..7caa9f26bc2 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 @@ -1,119 +1,119 @@ error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:10:13 + --> $DIR/incorrect-syntax-suggestions.rs:8:13 | LL | let _ = await bar(); | ^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await` error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:14:13 + --> $DIR/incorrect-syntax-suggestions.rs:12:13 | LL | let _ = await? bar(); | ^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await?` error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:18:13 + --> $DIR/incorrect-syntax-suggestions.rs:16:13 | LL | let _ = await bar()?; | ^^^^^^^^^^^^ help: `await` is a postfix operation: `bar()?.await` error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:23:13 + --> $DIR/incorrect-syntax-suggestions.rs:21:13 | LL | let _ = await { bar() }; | ^^^^^^^^^^^^^^^ help: `await` is a postfix operation: `{ bar() }.await` error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:27:13 + --> $DIR/incorrect-syntax-suggestions.rs:25:13 | LL | let _ = await(bar()); | ^^^^^^^^^^^^ help: `await` is a postfix operation: `(bar()).await` error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:31:13 + --> $DIR/incorrect-syntax-suggestions.rs:29:13 | LL | let _ = await { bar() }?; | ^^^^^^^^^^^^^^^ help: `await` is a postfix operation: `{ bar() }.await` error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:35:14 + --> $DIR/incorrect-syntax-suggestions.rs:33:14 | LL | let _ = (await bar())?; | ^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await` error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:39:24 + --> $DIR/incorrect-syntax-suggestions.rs:37:24 | LL | let _ = bar().await(); | ^^ help: `await` is not a method call, remove the parentheses error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:43:24 + --> $DIR/incorrect-syntax-suggestions.rs:41:24 | LL | let _ = bar().await()?; | ^^ help: `await` is not a method call, remove the parentheses error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:55:13 + --> $DIR/incorrect-syntax-suggestions.rs:53:13 | LL | let _ = await bar(); | ^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await` error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:60:13 + --> $DIR/incorrect-syntax-suggestions.rs:58:13 | LL | let _ = await? bar(); | ^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await?` error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:65:13 + --> $DIR/incorrect-syntax-suggestions.rs:63:13 | LL | let _ = await bar()?; | ^^^^^^^^^^^^ help: `await` is a postfix operation: `bar()?.await` error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:70:14 + --> $DIR/incorrect-syntax-suggestions.rs:68:14 | LL | let _ = (await bar())?; | ^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await` error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:75:24 + --> $DIR/incorrect-syntax-suggestions.rs:73:24 | LL | let _ = bar().await(); | ^^ help: `await` is not a method call, remove the parentheses error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:80:24 + --> $DIR/incorrect-syntax-suggestions.rs:78:24 | LL | let _ = bar().await()?; | ^^ help: `await` is not a method call, remove the parentheses error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:108:13 + --> $DIR/incorrect-syntax-suggestions.rs:106:13 | LL | let _ = await!(bar()); | ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await` error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:112:13 + --> $DIR/incorrect-syntax-suggestions.rs:110:13 | LL | let _ = await!(bar())?; | ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await` error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:117:17 + --> $DIR/incorrect-syntax-suggestions.rs:115:17 | LL | let _ = await!(bar())?; | ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await` error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:125:17 + --> $DIR/incorrect-syntax-suggestions.rs:123:17 | LL | let _ = await!(bar())?; | ^^^^^^^^^^^^^ help: `await` is a postfix operation: `bar().await` error: expected expression, found `=>` - --> $DIR/incorrect-syntax-suggestions.rs:133:25 + --> $DIR/incorrect-syntax-suggestions.rs:131:25 | LL | match await { await => () } | ----- ^^ expected expression @@ -121,13 +121,13 @@ LL | match await { await => () } | while parsing this incorrect await expression error: incorrect use of `await` - --> $DIR/incorrect-syntax-suggestions.rs:133:11 + --> $DIR/incorrect-syntax-suggestions.rs:131:11 | LL | match await { await => () } | ^^^^^^^^^^^^^^^^^^^^^ help: `await` is a postfix operation: `{ await => () }.await` error: expected one of `.`, `?`, `{`, or an operator, found `}` - --> $DIR/incorrect-syntax-suggestions.rs:136:1 + --> $DIR/incorrect-syntax-suggestions.rs:134:1 | LL | match await { await => () } | ----- - expected one of `.`, `?`, `{`, or an operator here @@ -138,7 +138,7 @@ LL | } | ^ unexpected token error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:55:13 + --> $DIR/incorrect-syntax-suggestions.rs:53:13 | LL | fn foo9() -> Result<(), ()> { | ---- this is not `async` @@ -146,7 +146,7 @@ LL | let _ = await bar(); | ^^^^^^^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:60:13 + --> $DIR/incorrect-syntax-suggestions.rs:58:13 | LL | fn foo10() -> Result<(), ()> { | ----- this is not `async` @@ -154,7 +154,7 @@ LL | let _ = await? bar(); | ^^^^^^^^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:65:13 + --> $DIR/incorrect-syntax-suggestions.rs:63:13 | LL | fn foo11() -> Result<(), ()> { | ----- this is not `async` @@ -162,7 +162,7 @@ LL | let _ = await bar()?; | ^^^^^^^^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:70:14 + --> $DIR/incorrect-syntax-suggestions.rs:68:14 | LL | fn foo12() -> Result<(), ()> { | ----- this is not `async` @@ -170,7 +170,7 @@ LL | let _ = (await bar())?; | ^^^^^^^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:75:13 + --> $DIR/incorrect-syntax-suggestions.rs:73:13 | LL | fn foo13() -> Result<(), ()> { | ----- this is not `async` @@ -178,7 +178,7 @@ LL | let _ = bar().await(); | ^^^^^^^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:80:13 + --> $DIR/incorrect-syntax-suggestions.rs:78:13 | LL | fn foo14() -> Result<(), ()> { | ----- this is not `async` @@ -186,7 +186,7 @@ LL | let _ = bar().await()?; | ^^^^^^^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:85:13 + --> $DIR/incorrect-syntax-suggestions.rs:83:13 | LL | fn foo15() -> Result<(), ()> { | ----- this is not `async` @@ -194,7 +194,7 @@ LL | let _ = bar().await; | ^^^^^^^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:89:13 + --> $DIR/incorrect-syntax-suggestions.rs:87:13 | LL | fn foo16() -> Result<(), ()> { | ----- this is not `async` @@ -202,7 +202,7 @@ LL | let _ = bar().await?; | ^^^^^^^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:94:17 + --> $DIR/incorrect-syntax-suggestions.rs:92:17 | LL | fn foo() -> Result<(), ()> { | --- this is not `async` @@ -210,7 +210,7 @@ LL | let _ = bar().await?; | ^^^^^^^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:101:17 + --> $DIR/incorrect-syntax-suggestions.rs:99:17 | LL | let foo = || { | -- this is not `async` @@ -218,7 +218,7 @@ LL | let _ = bar().await?; | ^^^^^^^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:117:17 + --> $DIR/incorrect-syntax-suggestions.rs:115:17 | LL | fn foo() -> Result<(), ()> { | --- this is not `async` @@ -226,7 +226,7 @@ LL | let _ = await!(bar())?; | ^^^^^^^^^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/incorrect-syntax-suggestions.rs:125:17 + --> $DIR/incorrect-syntax-suggestions.rs:123:17 | LL | let foo = || { | -- this is not `async` @@ -234,7 +234,7 @@ LL | let _ = await!(bar())?; | ^^^^^^^^^^^^^ only allowed inside `async` functions and blocks error[E0277]: the `?` operator can only be applied to values that implement `std::ops::Try` - --> $DIR/incorrect-syntax-suggestions.rs:18:19 + --> $DIR/incorrect-syntax-suggestions.rs:16:19 | LL | let _ = await bar()?; | ^^^^^^ the `?` operator cannot be applied to type `impl std::future::Future` diff --git a/src/test/ui/async-await/await-unsize.rs b/src/test/ui/async-await/await-unsize.rs index d5e21257f4f..aa09d4bdf08 100644 --- a/src/test/ui/async-await/await-unsize.rs +++ b/src/test/ui/async-await/await-unsize.rs @@ -3,8 +3,6 @@ // check-pass // edition:2018 -#![feature(async_await)] - async fn make_boxed_object() -> Box<dyn Send> { Box::new(()) as _ } diff --git a/src/test/ui/async-await/bound-normalization.rs b/src/test/ui/async-await/bound-normalization.rs index 8026350aaf2..5d260682f1d 100644 --- a/src/test/ui/async-await/bound-normalization.rs +++ b/src/test/ui/async-await/bound-normalization.rs @@ -1,8 +1,6 @@ // check-pass // edition:2018 -#![feature(async_await)] - // See issue 60414 trait Trait { diff --git a/src/test/ui/async-await/conditional-and-guaranteed-initialization.rs b/src/test/ui/async-await/conditional-and-guaranteed-initialization.rs index a5947e7f718..56f4cbbd190 100644 --- a/src/test/ui/async-await/conditional-and-guaranteed-initialization.rs +++ b/src/test/ui/async-await/conditional-and-guaranteed-initialization.rs @@ -2,8 +2,6 @@ // edition:2018 // compile-flags: --crate-type lib -#![feature(async_await)] - async fn conditional_and_guaranteed_initialization(x: usize) -> usize { let y; if x > 5 { diff --git a/src/test/ui/async-await/dont-print-desugared-async.rs b/src/test/ui/async-await/dont-print-desugared-async.rs index 8150a260866..68341a24c4e 100644 --- a/src/test/ui/async-await/dont-print-desugared-async.rs +++ b/src/test/ui/async-await/dont-print-desugared-async.rs @@ -1,7 +1,6 @@ // Test that we don't show variables with from async fn desugaring // edition:2018 -#![feature(async_await)] async fn async_fn(&ref mut s: &[i32]) {} //~^ ERROR cannot borrow data in a `&` reference as mutable [E0596] diff --git a/src/test/ui/async-await/dont-print-desugared-async.stderr b/src/test/ui/async-await/dont-print-desugared-async.stderr index 47726ba65df..2bf1e77f09b 100644 --- a/src/test/ui/async-await/dont-print-desugared-async.stderr +++ b/src/test/ui/async-await/dont-print-desugared-async.stderr @@ -1,5 +1,5 @@ error[E0596]: cannot borrow data in a `&` reference as mutable - --> $DIR/dont-print-desugared-async.rs:6:20 + --> $DIR/dont-print-desugared-async.rs:5:20 | LL | async fn async_fn(&ref mut s: &[i32]) {} | -^^^^^^^^^ diff --git a/src/test/ui/async-await/dont-suggest-missing-await.rs b/src/test/ui/async-await/dont-suggest-missing-await.rs index d551ef57985..a8e5b38ec1d 100644 --- a/src/test/ui/async-await/dont-suggest-missing-await.rs +++ b/src/test/ui/async-await/dont-suggest-missing-await.rs @@ -2,8 +2,6 @@ // This test ensures we don't make the suggestion in bodies that aren't `async`. -#![feature(async_await)] - fn take_u32(x: u32) {} async fn make_u32() -> u32 { diff --git a/src/test/ui/async-await/dont-suggest-missing-await.stderr b/src/test/ui/async-await/dont-suggest-missing-await.stderr index c60b0d1f30e..c87e0bc221d 100644 --- a/src/test/ui/async-await/dont-suggest-missing-await.stderr +++ b/src/test/ui/async-await/dont-suggest-missing-await.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/dont-suggest-missing-await.rs:16:18 + --> $DIR/dont-suggest-missing-await.rs:14:18 | LL | take_u32(x) | ^ expected u32, found opaque type diff --git a/src/test/ui/async-await/drop-order/drop-order-for-async-fn-parameters-by-ref-binding.rs b/src/test/ui/async-await/drop-order/drop-order-for-async-fn-parameters-by-ref-binding.rs index dfd8b2e361e..9817d377a78 100644 --- a/src/test/ui/async-await/drop-order/drop-order-for-async-fn-parameters-by-ref-binding.rs +++ b/src/test/ui/async-await/drop-order/drop-order-for-async-fn-parameters-by-ref-binding.rs @@ -3,7 +3,6 @@ // run-pass #![allow(unused_variables)] -#![feature(async_await)] // Test that the drop order for parameters in a fn and async fn matches up. Also test that // parameters (used or unused) are not dropped until the async fn completes execution. diff --git a/src/test/ui/async-await/drop-order/drop-order-for-async-fn-parameters.rs b/src/test/ui/async-await/drop-order/drop-order-for-async-fn-parameters.rs index 2a74485afb4..00072786a50 100644 --- a/src/test/ui/async-await/drop-order/drop-order-for-async-fn-parameters.rs +++ b/src/test/ui/async-await/drop-order/drop-order-for-async-fn-parameters.rs @@ -3,7 +3,6 @@ // run-pass #![allow(unused_variables)] -#![feature(async_await)] // Test that the drop order for parameters in a fn and async fn matches up. Also test that // parameters (used or unused) are not dropped until the async fn completes execution. diff --git a/src/test/ui/async-await/drop-order/drop-order-for-locals-when-cancelled.rs b/src/test/ui/async-await/drop-order/drop-order-for-locals-when-cancelled.rs index db396d3957e..5d020c9a526 100644 --- a/src/test/ui/async-await/drop-order/drop-order-for-locals-when-cancelled.rs +++ b/src/test/ui/async-await/drop-order/drop-order-for-locals-when-cancelled.rs @@ -2,9 +2,7 @@ // edition:2018 // run-pass -#![allow(unused_variables)] #![deny(dead_code)] -#![feature(async_await)] // Test that the drop order for locals in a fn and async fn matches up. extern crate arc_wake; diff --git a/src/test/ui/async-await/drop-order/drop-order-locals-are-hidden.rs b/src/test/ui/async-await/drop-order/drop-order-locals-are-hidden.rs index bcdb8878eb5..79dedb1ba28 100644 --- a/src/test/ui/async-await/drop-order/drop-order-locals-are-hidden.rs +++ b/src/test/ui/async-await/drop-order/drop-order-locals-are-hidden.rs @@ -1,8 +1,5 @@ // edition:2018 -#![allow(unused_variables)] -#![feature(async_await)] - async fn foobar_async(x: u32, (a, _, _c): (u32, u32, u32), _: u32, _y: u32) { assert_eq!(__arg1, (1, 2, 3)); //~ ERROR cannot find value `__arg1` in this scope [E0425] assert_eq!(__arg2, 4); //~ ERROR cannot find value `__arg2` in this scope [E0425] diff --git a/src/test/ui/async-await/drop-order/drop-order-locals-are-hidden.stderr b/src/test/ui/async-await/drop-order/drop-order-locals-are-hidden.stderr index 484e1f4f426..aa04a613f47 100644 --- a/src/test/ui/async-await/drop-order/drop-order-locals-are-hidden.stderr +++ b/src/test/ui/async-await/drop-order/drop-order-locals-are-hidden.stderr @@ -1,23 +1,23 @@ error[E0425]: cannot find value `__arg1` in this scope - --> $DIR/drop-order-locals-are-hidden.rs:7:16 + --> $DIR/drop-order-locals-are-hidden.rs:4:16 | LL | assert_eq!(__arg1, (1, 2, 3)); | ^^^^^^ not found in this scope error[E0425]: cannot find value `__arg2` in this scope - --> $DIR/drop-order-locals-are-hidden.rs:8:16 + --> $DIR/drop-order-locals-are-hidden.rs:5:16 | LL | assert_eq!(__arg2, 4); | ^^^^^^ not found in this scope error[E0425]: cannot find value `__arg0` in this scope - --> $DIR/drop-order-locals-are-hidden.rs:12:16 + --> $DIR/drop-order-locals-are-hidden.rs:9:16 | LL | assert_eq!(__arg0, 1); | ^^^^^^ not found in this scope error[E0425]: cannot find value `__arg1` in this scope - --> $DIR/drop-order-locals-are-hidden.rs:13:16 + --> $DIR/drop-order-locals-are-hidden.rs:10:16 | LL | assert_eq!(__arg1, 2); | ^^^^^^ not found in this scope diff --git a/src/test/ui/async-await/drop-order/drop-order-when-cancelled.rs b/src/test/ui/async-await/drop-order/drop-order-when-cancelled.rs index 410a623681d..84fe79348c6 100644 --- a/src/test/ui/async-await/drop-order/drop-order-when-cancelled.rs +++ b/src/test/ui/async-await/drop-order/drop-order-when-cancelled.rs @@ -2,9 +2,6 @@ // edition:2018 // run-pass -#![allow(unused_variables)] -#![feature(async_await)] - // Test that the drop order for parameters in a fn and async fn matches up. Also test that // parameters (used or unused) are not dropped until the async fn is cancelled. // This file is mostly copy-pasted from drop-order-for-async-fn-parameters.rs diff --git a/src/test/ui/async-await/edition-deny-async-fns-2015.rs b/src/test/ui/async-await/edition-deny-async-fns-2015.rs index a5bc1810154..c85896150c2 100644 --- a/src/test/ui/async-await/edition-deny-async-fns-2015.rs +++ b/src/test/ui/async-await/edition-deny-async-fns-2015.rs @@ -1,7 +1,5 @@ // edition:2015 -#![feature(async_await)] - async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition fn baz() { async fn foo() {} } //~ ERROR `async fn` is not permitted in the 2015 edition diff --git a/src/test/ui/async-await/edition-deny-async-fns-2015.stderr b/src/test/ui/async-await/edition-deny-async-fns-2015.stderr index efb4462095d..d3f88af09d1 100644 --- a/src/test/ui/async-await/edition-deny-async-fns-2015.stderr +++ b/src/test/ui/async-await/edition-deny-async-fns-2015.stderr @@ -1,59 +1,59 @@ error[E0670]: `async fn` is not permitted in the 2015 edition - --> $DIR/edition-deny-async-fns-2015.rs:5:1 + --> $DIR/edition-deny-async-fns-2015.rs:3:1 | LL | async fn foo() {} | ^^^^^ error[E0670]: `async fn` is not permitted in the 2015 edition - --> $DIR/edition-deny-async-fns-2015.rs:7:12 + --> $DIR/edition-deny-async-fns-2015.rs:5:12 | LL | fn baz() { async fn foo() {} } | ^^^^^ error[E0670]: `async fn` is not permitted in the 2015 edition - --> $DIR/edition-deny-async-fns-2015.rs:10:5 + --> $DIR/edition-deny-async-fns-2015.rs:8:5 | LL | async fn bar() {} | ^^^^^ error[E0670]: `async fn` is not permitted in the 2015 edition - --> $DIR/edition-deny-async-fns-2015.rs:9:1 + --> $DIR/edition-deny-async-fns-2015.rs:7:1 | LL | async fn async_baz() { | ^^^^^ error[E0670]: `async fn` is not permitted in the 2015 edition - --> $DIR/edition-deny-async-fns-2015.rs:16:5 + --> $DIR/edition-deny-async-fns-2015.rs:14:5 | LL | async fn foo() {} | ^^^^^ error[E0670]: `async fn` is not permitted in the 2015 edition - --> $DIR/edition-deny-async-fns-2015.rs:20:5 + --> $DIR/edition-deny-async-fns-2015.rs:18:5 | LL | async fn foo() {} | ^^^^^ error[E0670]: `async fn` is not permitted in the 2015 edition - --> $DIR/edition-deny-async-fns-2015.rs:38:9 + --> $DIR/edition-deny-async-fns-2015.rs:36:9 | LL | async fn bar() {} | ^^^^^ error[E0670]: `async fn` is not permitted in the 2015 edition - --> $DIR/edition-deny-async-fns-2015.rs:28:9 + --> $DIR/edition-deny-async-fns-2015.rs:26:9 | LL | async fn foo() {} | ^^^^^ error[E0670]: `async fn` is not permitted in the 2015 edition - --> $DIR/edition-deny-async-fns-2015.rs:33:13 + --> $DIR/edition-deny-async-fns-2015.rs:31:13 | LL | async fn bar() {} | ^^^^^ error[E0706]: trait fns cannot be declared `async` - --> $DIR/edition-deny-async-fns-2015.rs:20:5 + --> $DIR/edition-deny-async-fns-2015.rs:18:5 | LL | async fn foo() {} | ^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/async-await/generics-and-bounds.rs b/src/test/ui/async-await/generics-and-bounds.rs index 8b60f2f82f1..963b19b34a6 100644 --- a/src/test/ui/async-await/generics-and-bounds.rs +++ b/src/test/ui/async-await/generics-and-bounds.rs @@ -2,8 +2,6 @@ // edition:2018 // compile-flags: --crate-type lib -#![feature(async_await)] - use std::future::Future; pub async fn simple_generic<T>() {} diff --git a/src/test/ui/async-await/issue-60709.rs b/src/test/ui/async-await/issue-60709.rs index ad0b49fa4a2..9ee419c4a56 100644 --- a/src/test/ui/async-await/issue-60709.rs +++ b/src/test/ui/async-await/issue-60709.rs @@ -4,9 +4,6 @@ // run-pass -#![feature(async_await)] -#![allow(unused)] - use std::future::Future; use std::task::Poll; use std::task::Context; diff --git a/src/test/ui/async-await/issue-61452.rs b/src/test/ui/async-await/issue-61452.rs index 20b9b645dae..9381251ad69 100644 --- a/src/test/ui/async-await/issue-61452.rs +++ b/src/test/ui/async-await/issue-61452.rs @@ -1,5 +1,4 @@ // edition:2018 -#![feature(async_await)] pub async fn f(x: Option<usize>) { x.take(); diff --git a/src/test/ui/async-await/issue-61452.stderr b/src/test/ui/async-await/issue-61452.stderr index 742490d8de4..5eb4b548717 100644 --- a/src/test/ui/async-await/issue-61452.stderr +++ b/src/test/ui/async-await/issue-61452.stderr @@ -1,5 +1,5 @@ error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable - --> $DIR/issue-61452.rs:5:5 + --> $DIR/issue-61452.rs:4:5 | LL | pub async fn f(x: Option<usize>) { | - help: consider changing this to be mutable: `mut x` @@ -7,7 +7,7 @@ LL | x.take(); | ^ cannot borrow as mutable error[E0384]: cannot assign twice to immutable variable `x` - --> $DIR/issue-61452.rs:10:5 + --> $DIR/issue-61452.rs:9:5 | LL | pub async fn g(x: usize) { | - diff --git a/src/test/ui/async-await/issue-61793.rs b/src/test/ui/async-await/issue-61793.rs index a18fad8bb91..f6084be9167 100644 --- a/src/test/ui/async-await/issue-61793.rs +++ b/src/test/ui/async-await/issue-61793.rs @@ -6,9 +6,6 @@ // build-pass (FIXME(62277): could be check-pass?) // edition:2018 -#![feature(async_await)] -#![allow(unused)] - async fn foo<F>(_: &(), _: F) {} fn main() { diff --git a/src/test/ui/async-await/issue-61949-self-return-type.rs b/src/test/ui/async-await/issue-61949-self-return-type.rs new file mode 100644 index 00000000000..6a28c69193d --- /dev/null +++ b/src/test/ui/async-await/issue-61949-self-return-type.rs @@ -0,0 +1,27 @@ +// ignore-tidy-linelength +// edition:2018 + +// This test checks that `Self` is prohibited as a return type. See #61949 for context. + +pub struct Foo<'a> { + pub bar: &'a i32, +} + +impl<'a> Foo<'a> { + pub async fn new(_bar: &'a i32) -> Self { + //~^ ERROR `async fn` return type cannot contain a projection or `Self` that references lifetimes from a parent scope + Foo { + bar: &22 + } + } +} + +async fn foo() { + let x = { + let bar = 22; + Foo::new(&bar).await + }; + drop(x); +} + +fn main() { } diff --git a/src/test/ui/async-await/issue-61949-self-return-type.stderr b/src/test/ui/async-await/issue-61949-self-return-type.stderr new file mode 100644 index 00000000000..12fb77d8dd6 --- /dev/null +++ b/src/test/ui/async-await/issue-61949-self-return-type.stderr @@ -0,0 +1,8 @@ +error: `async fn` return type cannot contain a projection or `Self` that references lifetimes from a parent scope + --> $DIR/issue-61949-self-return-type.rs:11:40 + | +LL | pub async fn new(_bar: &'a i32) -> Self { + | ^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/async-await/issue-62658.rs b/src/test/ui/async-await/issue-62658.rs index 90fbb47bffd..d0af01e0c00 100644 --- a/src/test/ui/async-await/issue-62658.rs +++ b/src/test/ui/async-await/issue-62658.rs @@ -4,8 +4,6 @@ // build-pass // edition:2018 -#![feature(async_await)] - async fn noop() {} async fn foo() { diff --git a/src/test/ui/async-await/issues/issue-51719.rs b/src/test/ui/async-await/issues/issue-51719.rs index 361a49c2774..09241f982aa 100644 --- a/src/test/ui/async-await/issues/issue-51719.rs +++ b/src/test/ui/async-await/issues/issue-51719.rs @@ -2,8 +2,6 @@ // // Tests that the .await syntax can't be used to make a generator -#![feature(async_await)] - async fn foo() {} fn make_generator() { diff --git a/src/test/ui/async-await/issues/issue-51719.stderr b/src/test/ui/async-await/issues/issue-51719.stderr index 2a9fb6cf0df..6c3c8889da7 100644 --- a/src/test/ui/async-await/issues/issue-51719.stderr +++ b/src/test/ui/async-await/issues/issue-51719.stderr @@ -1,5 +1,5 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/issue-51719.rs:10:19 + --> $DIR/issue-51719.rs:8:19 | LL | let _gen = || foo().await; | -- ^^^^^^^^^^^ only allowed inside `async` functions and blocks diff --git a/src/test/ui/async-await/issues/issue-51751.rs b/src/test/ui/async-await/issues/issue-51751.rs index 7afd7ecc826..bc85a96cea9 100644 --- a/src/test/ui/async-await/issues/issue-51751.rs +++ b/src/test/ui/async-await/issues/issue-51751.rs @@ -1,7 +1,5 @@ // edition:2018 -#![feature(async_await)] - async fn inc(limit: i64) -> i64 { limit + 1 } diff --git a/src/test/ui/async-await/issues/issue-51751.stderr b/src/test/ui/async-await/issues/issue-51751.stderr index 97b63d1590e..e50c78534f8 100644 --- a/src/test/ui/async-await/issues/issue-51751.stderr +++ b/src/test/ui/async-await/issues/issue-51751.stderr @@ -1,5 +1,5 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/issue-51751.rs:11:20 + --> $DIR/issue-51751.rs:9:20 | LL | fn main() { | ---- this is not `async` diff --git a/src/test/ui/async-await/issues/issue-53249.rs b/src/test/ui/async-await/issues/issue-53249.rs index c57dc6b0ef6..5cae0704444 100644 --- a/src/test/ui/async-await/issues/issue-53249.rs +++ b/src/test/ui/async-await/issues/issue-53249.rs @@ -1,7 +1,7 @@ // build-pass (FIXME(62277): could be check-pass?) // edition:2018 -#![feature(arbitrary_self_types, async_await)] +#![feature(arbitrary_self_types)] use std::task::{self, Poll}; use std::future::Future; diff --git a/src/test/ui/async-await/issues/issue-54752-async-block.rs b/src/test/ui/async-await/issues/issue-54752-async-block.rs index 0036de90b25..64f260cfe01 100644 --- a/src/test/ui/async-await/issues/issue-54752-async-block.rs +++ b/src/test/ui/async-await/issues/issue-54752-async-block.rs @@ -3,7 +3,4 @@ // edition:2018 // pp-exact -#![feature(async_await)] -#![allow(unused_parens)] - fn main() { let _a = (async { }); } diff --git a/src/test/ui/async-await/issues/issue-54974.rs b/src/test/ui/async-await/issues/issue-54974.rs index 040989b33fc..9adc0a82323 100644 --- a/src/test/ui/async-await/issues/issue-54974.rs +++ b/src/test/ui/async-await/issues/issue-54974.rs @@ -1,8 +1,6 @@ // build-pass (FIXME(62277): could be check-pass?) // edition:2018 -#![feature(async_await)] - use std::sync::Arc; trait SomeTrait: Send + Sync + 'static { diff --git a/src/test/ui/async-await/issues/issue-55324.rs b/src/test/ui/async-await/issues/issue-55324.rs index 4f383a51a88..1d77d420127 100644 --- a/src/test/ui/async-await/issues/issue-55324.rs +++ b/src/test/ui/async-await/issues/issue-55324.rs @@ -1,11 +1,8 @@ // build-pass (FIXME(62277): could be check-pass?) // edition:2018 -#![feature(async_await)] - use std::future::Future; -#[allow(unused)] async fn foo<F: Future<Output = i32>>(x: &i32, future: F) -> i32 { let y = future.await; *x + y diff --git a/src/test/ui/async-await/issues/issue-55809.rs b/src/test/ui/async-await/issues/issue-55809.rs index b7e60b773b4..3b271775a38 100644 --- a/src/test/ui/async-await/issues/issue-55809.rs +++ b/src/test/ui/async-await/issues/issue-55809.rs @@ -1,8 +1,6 @@ // edition:2018 // run-pass -#![feature(async_await)] - trait Foo { } impl Foo for () { } diff --git a/src/test/ui/async-await/issues/issue-58885.rs b/src/test/ui/async-await/issues/issue-58885.rs index 47744aeea60..72a45b5007d 100644 --- a/src/test/ui/async-await/issues/issue-58885.rs +++ b/src/test/ui/async-await/issues/issue-58885.rs @@ -1,8 +1,6 @@ // build-pass (FIXME(62277): could be check-pass?) // edition:2018 -#![feature(async_await)] - struct Xyz { a: u64, } diff --git a/src/test/ui/async-await/issues/issue-59001.rs b/src/test/ui/async-await/issues/issue-59001.rs index 9334ddb0af5..ea780d9f622 100644 --- a/src/test/ui/async-await/issues/issue-59001.rs +++ b/src/test/ui/async-await/issues/issue-59001.rs @@ -1,11 +1,8 @@ // build-pass (FIXME(62277): could be check-pass?) // edition:2018 -#![feature(async_await)] - use std::future::Future; -#[allow(unused)] async fn enter<'a, F, R>(mut callback: F) where F: FnMut(&'a mut i32) -> R, diff --git a/src/test/ui/async-await/issues/issue-59972.rs b/src/test/ui/async-await/issues/issue-59972.rs index 8f4254b10ce..154226e8bb8 100644 --- a/src/test/ui/async-await/issues/issue-59972.rs +++ b/src/test/ui/async-await/issues/issue-59972.rs @@ -6,8 +6,6 @@ // compile-flags: --edition=2018 -#![feature(async_await)] - pub enum Uninhabited { } fn uninhabited_async() -> Uninhabited { @@ -16,14 +14,12 @@ fn uninhabited_async() -> Uninhabited { async fn noop() { } -#[allow(unused)] async fn contains_never() { let error = uninhabited_async(); noop().await; let error2 = error; } -#[allow(unused)] async fn overlap_never() { let error1 = uninhabited_async(); noop().await; @@ -35,6 +31,4 @@ async fn overlap_never() { #[allow(unused_must_use)] fn main() { - contains_never(); - overlap_never(); } diff --git a/src/test/ui/async-await/issues/issue-60518.rs b/src/test/ui/async-await/issues/issue-60518.rs index e4bdc96511e..1ca05160751 100644 --- a/src/test/ui/async-await/issues/issue-60518.rs +++ b/src/test/ui/async-await/issues/issue-60518.rs @@ -1,8 +1,6 @@ // build-pass (FIXME(62277): could be check-pass?) // edition:2018 -#![feature(async_await)] - // This is a regression test to ensure that simple bindings (where replacement arguments aren't // created during async fn lowering) that have their DefId used during HIR lowering (such as impl // trait) are visited during def collection and thus have a DefId. diff --git a/src/test/ui/async-await/issues/issue-60655-latebound-regions.rs b/src/test/ui/async-await/issues/issue-60655-latebound-regions.rs index 99213e64d16..0d015e54f8b 100644 --- a/src/test/ui/async-await/issues/issue-60655-latebound-regions.rs +++ b/src/test/ui/async-await/issues/issue-60655-latebound-regions.rs @@ -3,7 +3,6 @@ // build-pass (FIXME(62277): could be check-pass?) // edition:2018 -#![feature(async_await)] #![feature(type_alias_impl_trait)] use std::future::Future; diff --git a/src/test/ui/async-await/issues/issue-60674.rs b/src/test/ui/async-await/issues/issue-60674.rs index 99cdcbafc76..c0e34a8df77 100644 --- a/src/test/ui/async-await/issues/issue-60674.rs +++ b/src/test/ui/async-await/issues/issue-60674.rs @@ -1,7 +1,6 @@ // aux-build:issue-60674.rs // build-pass (FIXME(62277): could be check-pass?) // edition:2018 -#![feature(async_await)] // This is a regression test that ensures that `mut` patterns are not lost when provided as input // to a proc macro. diff --git a/src/test/ui/async-await/issues/issue-61187.rs b/src/test/ui/async-await/issues/issue-61187.rs index 8b939b43b8b..8585a425111 100644 --- a/src/test/ui/async-await/issues/issue-61187.rs +++ b/src/test/ui/async-await/issues/issue-61187.rs @@ -1,8 +1,6 @@ // edition:2018 -#![feature(async_await)] -fn main() { -} +fn main() {} async fn response(data: Vec<u8>) { data.reverse(); //~ ERROR E0596 diff --git a/src/test/ui/async-await/issues/issue-61187.stderr b/src/test/ui/async-await/issues/issue-61187.stderr index a0314226320..4d361c824dd 100644 --- a/src/test/ui/async-await/issues/issue-61187.stderr +++ b/src/test/ui/async-await/issues/issue-61187.stderr @@ -1,5 +1,5 @@ error[E0596]: cannot borrow `data` as mutable, as it is not declared as mutable - --> $DIR/issue-61187.rs:8:5 + --> $DIR/issue-61187.rs:6:5 | LL | async fn response(data: Vec<u8>) { | ---- help: consider changing this to be mutable: `mut data` diff --git a/src/test/ui/async-await/issues/issue-61986.rs b/src/test/ui/async-await/issues/issue-61986.rs index 77ecc47dfef..879bc6912fc 100644 --- a/src/test/ui/async-await/issues/issue-61986.rs +++ b/src/test/ui/async-await/issues/issue-61986.rs @@ -4,8 +4,6 @@ // Tests that we properly handle StorageDead/StorageLives for temporaries // created in async loop bodies. -#![feature(async_await)] - async fn bar() -> Option<()> { Some(()) } diff --git a/src/test/ui/async-await/issues/issue-62009-1.rs b/src/test/ui/async-await/issues/issue-62009-1.rs index ac6605bceff..3ee7ab2e9d1 100644 --- a/src/test/ui/async-await/issues/issue-62009-1.rs +++ b/src/test/ui/async-await/issues/issue-62009-1.rs @@ -1,7 +1,5 @@ // edition:2018 -#![feature(async_await)] - async fn print_dur() {} fn main() { 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 2bbb6d079ea..cd155f0fc32 100644 --- a/src/test/ui/async-await/issues/issue-62009-1.stderr +++ b/src/test/ui/async-await/issues/issue-62009-1.stderr @@ -1,5 +1,5 @@ error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/issue-62009-1.rs:8:5 + --> $DIR/issue-62009-1.rs:6:5 | LL | fn main() { | ---- this is not `async` @@ -7,7 +7,7 @@ LL | async { let (); }.await; | ^^^^^^^^^^^^^^^^^^^^^^^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/issue-62009-1.rs:10:5 + --> $DIR/issue-62009-1.rs:8:5 | LL | fn main() { | ---- this is not `async` @@ -19,7 +19,7 @@ LL | | }.await; | |___________^ only allowed inside `async` functions and blocks error[E0728]: `await` is only allowed inside `async` functions and blocks - --> $DIR/issue-62009-1.rs:14:5 + --> $DIR/issue-62009-1.rs:12:5 | LL | fn main() { | ---- this is not `async` @@ -27,11 +27,11 @@ LL | fn main() { LL | (|_| 2333).await; | ^^^^^^^^^^^^^^^^ only allowed inside `async` functions and blocks -error[E0277]: the trait bound `[closure@$DIR/issue-62009-1.rs:14:5: 14:15]: std::future::Future` is not satisfied - --> $DIR/issue-62009-1.rs:14:5 +error[E0277]: the trait bound `[closure@$DIR/issue-62009-1.rs:12:5: 12:15]: std::future::Future` is not satisfied + --> $DIR/issue-62009-1.rs:12:5 | LL | (|_| 2333).await; - | ^^^^^^^^^^^^^^^^ the trait `std::future::Future` is not implemented for `[closure@$DIR/issue-62009-1.rs:14:5: 14:15]` + | ^^^^^^^^^^^^^^^^ the trait `std::future::Future` is not implemented for `[closure@$DIR/issue-62009-1.rs:12:5: 12:15]` | = note: required by `std::future::poll_with_tls_context` diff --git a/src/test/ui/async-await/issues/issue-62009-2.rs b/src/test/ui/async-await/issues/issue-62009-2.rs index 52b62eaa9e0..cb7336e6134 100644 --- a/src/test/ui/async-await/issues/issue-62009-2.rs +++ b/src/test/ui/async-await/issues/issue-62009-2.rs @@ -1,6 +1,6 @@ // edition:2018 -#![feature(async_await, async_closure)] +#![feature(async_closure)] async fn print_dur() {} diff --git a/src/test/ui/async-await/issues/issue-62517-1.rs b/src/test/ui/async-await/issues/issue-62517-1.rs new file mode 100644 index 00000000000..4689ce36a78 --- /dev/null +++ b/src/test/ui/async-await/issues/issue-62517-1.rs @@ -0,0 +1,21 @@ +// Regression test for #62517. We used to ICE when you had an `async +// fn` with an `impl Trait` return that mentioned a `dyn Bar` with no +// explicit lifetime bound. +// +// edition:2018 +// check-pass + +trait FirstTrait {} +trait SecondTrait { + type Item: ?Sized; +} + +async fn foo(x: &str) -> impl SecondTrait<Item = dyn FirstTrait> { +} + + +impl<T> SecondTrait for T { + type Item = dyn FirstTrait; +} + +fn main() { } diff --git a/src/test/ui/async-await/issues/issue-62517-2.rs b/src/test/ui/async-await/issues/issue-62517-2.rs new file mode 100644 index 00000000000..aaf28d6c132 --- /dev/null +++ b/src/test/ui/async-await/issues/issue-62517-2.rs @@ -0,0 +1,16 @@ +// Regression test for #62517. We used to ICE when you had an `async +// fn` with an `impl Trait` return that mentioned a `dyn Bar` with no +// explicit lifetime bound. +// +// edition:2018 +// check-pass + +trait Object {} + +trait Alpha<Param: ?Sized> {} + +async fn foo<'a>(_: &'a ()) -> impl Alpha<dyn Object> {} + +impl<T> Alpha<dyn Object> for T { } + +fn main() { } diff --git a/src/test/ui/async-await/issues/issue-63388-1.nll.stderr b/src/test/ui/async-await/issues/issue-63388-1.nll.stderr new file mode 100644 index 00000000000..22610fe54a4 --- /dev/null +++ b/src/test/ui/async-await/issues/issue-63388-1.nll.stderr @@ -0,0 +1,24 @@ +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/issue-63388-1.rs:12:10 + | +LL | ) -> &dyn Foo + | ^^^^^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#22r + +error: lifetime may not live long enough + --> $DIR/issue-63388-1.rs:13:5 + | +LL | async fn do_sth<'a>( + | -- lifetime `'a` defined here +LL | &'a self, foo: &dyn Foo + | - lifetime `'_` defined here +LL | ) -> &dyn Foo +LL | / { +LL | | foo +LL | | } + | |_____^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'_` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/async-await/issues/issue-63388-1.rs b/src/test/ui/async-await/issues/issue-63388-1.rs new file mode 100644 index 00000000000..3cde5de2198 --- /dev/null +++ b/src/test/ui/async-await/issues/issue-63388-1.rs @@ -0,0 +1,18 @@ +// edition:2018 + +struct Xyz { + a: u64, +} + +trait Foo {} + +impl Xyz { + async fn do_sth<'a>( + &'a self, foo: &dyn Foo + ) -> &dyn Foo //~ ERROR lifetime mismatch + { + foo + } +} + +fn main() {} diff --git a/src/test/ui/async-await/issues/issue-63388-1.stderr b/src/test/ui/async-await/issues/issue-63388-1.stderr new file mode 100644 index 00000000000..a54cadb0cd2 --- /dev/null +++ b/src/test/ui/async-await/issues/issue-63388-1.stderr @@ -0,0 +1,12 @@ +error[E0623]: lifetime mismatch + --> $DIR/issue-63388-1.rs:12:10 + | +LL | &'a self, foo: &dyn Foo + | -------- this parameter and the return type are declared with different lifetimes... +LL | ) -> &dyn Foo + | ^^^^^^^^ + | | + | ...but data from `foo` is returned here + +error: aborting due to previous error + diff --git a/src/test/ui/async-await/issues/issue-63388-2.nll.stderr b/src/test/ui/async-await/issues/issue-63388-2.nll.stderr new file mode 100644 index 00000000000..7781af89dea --- /dev/null +++ b/src/test/ui/async-await/issues/issue-63388-2.nll.stderr @@ -0,0 +1,11 @@ +error[E0106]: missing lifetime specifier + --> $DIR/issue-63388-2.rs:12:10 + | +LL | ) -> &dyn Foo + | ^ help: consider using the named lifetime: `&'a` + | + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `foo` or `bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0106`. diff --git a/src/test/ui/async-await/issues/issue-63388-2.rs b/src/test/ui/async-await/issues/issue-63388-2.rs new file mode 100644 index 00000000000..73e7f25f97d --- /dev/null +++ b/src/test/ui/async-await/issues/issue-63388-2.rs @@ -0,0 +1,18 @@ +// edition:2018 + +struct Xyz { + a: u64, +} + +trait Foo {} + +impl Xyz { + async fn do_sth<'a>( + foo: &dyn Foo, bar: &'a dyn Foo //~ ERROR cannot infer + ) -> &dyn Foo //~ ERROR missing lifetime specifier + { + foo + } +} + +fn main() {} diff --git a/src/test/ui/async-await/issues/issue-63388-2.stderr b/src/test/ui/async-await/issues/issue-63388-2.stderr new file mode 100644 index 00000000000..1edeb3d5493 --- /dev/null +++ b/src/test/ui/async-await/issues/issue-63388-2.stderr @@ -0,0 +1,29 @@ +error[E0106]: missing lifetime specifier + --> $DIR/issue-63388-2.rs:12:10 + | +LL | ) -> &dyn Foo + | ^ help: consider using the named lifetime: `&'a` + | + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `foo` or `bar` + +error: cannot infer an appropriate lifetime + --> $DIR/issue-63388-2.rs:11:9 + | +LL | foo: &dyn Foo, bar: &'a dyn Foo + | ^^^ ...but this borrow... +LL | ) -> &dyn Foo + | -------- this return type evaluates to the `'static` lifetime... + | +note: ...can't outlive the lifetime '_ as defined on the method body at 11:14 + --> $DIR/issue-63388-2.rs:11:14 + | +LL | foo: &dyn Foo, bar: &'a dyn Foo + | ^ +help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime '_ as defined on the method body at 11:14 + | +LL | ) -> &dyn Foo + '_ + | ^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0106`. diff --git a/src/test/ui/async-await/issues/issue-63388-3.rs b/src/test/ui/async-await/issues/issue-63388-3.rs new file mode 100644 index 00000000000..1a9822e02fa --- /dev/null +++ b/src/test/ui/async-await/issues/issue-63388-3.rs @@ -0,0 +1,17 @@ +// edition:2018 +// check-pass + +struct Xyz { + a: u64, +} + +trait Foo {} + +impl Xyz { + async fn do_sth( + &self, foo: &dyn Foo + ) { + } +} + +fn main() {} diff --git a/src/test/ui/async-await/issues/issue-63388-4.rs b/src/test/ui/async-await/issues/issue-63388-4.rs new file mode 100644 index 00000000000..58f9dacb3bc --- /dev/null +++ b/src/test/ui/async-await/issues/issue-63388-4.rs @@ -0,0 +1,10 @@ +// check-pass +// edition:2018 + +struct A; + +impl A { + async fn foo(&self, f: &u32) -> &A { self } +} + +fn main() { } diff --git a/src/test/ui/async-await/issues/non-async-enclosing-span.rs b/src/test/ui/async-await/issues/non-async-enclosing-span.rs new file mode 100644 index 00000000000..d47c2137725 --- /dev/null +++ b/src/test/ui/async-await/issues/non-async-enclosing-span.rs @@ -0,0 +1,11 @@ +// edition:2018 + +async fn do_the_thing() -> u8 { + 8 +} +// #63398: point at the enclosing scope and not the previously seen closure +fn main() { //~ NOTE this is not `async` + let x = move || {}; + let y = do_the_thing().await; //~ ERROR `await` is only allowed inside `async` functions + //~^ NOTE only allowed inside `async` functions and blocks +} 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 new file mode 100644 index 00000000000..49ebf414c55 --- /dev/null +++ b/src/test/ui/async-await/issues/non-async-enclosing-span.stderr @@ -0,0 +1,11 @@ +error[E0728]: `await` is only allowed inside `async` functions and blocks + --> $DIR/non-async-enclosing-span.rs:9:13 + | +LL | fn main() { + | ---- this is not `async` +LL | let x = move || {}; +LL | let y = do_the_thing().await; + | ^^^^^^^^^^^^^^^^^^^^ only allowed inside `async` functions and blocks + +error: aborting due to previous error + diff --git a/src/test/ui/async-await/move-part-await-return-rest-struct.rs b/src/test/ui/async-await/move-part-await-return-rest-struct.rs index 9bd7a515cbd..39ea2aae563 100644 --- a/src/test/ui/async-await/move-part-await-return-rest-struct.rs +++ b/src/test/ui/async-await/move-part-await-return-rest-struct.rs @@ -2,8 +2,6 @@ // edition:2018 // compile-flags: --crate-type lib -#![feature(async_await)] - struct Small { x: Vec<usize>, y: Vec<usize>, diff --git a/src/test/ui/async-await/move-part-await-return-rest-tuple.rs b/src/test/ui/async-await/move-part-await-return-rest-tuple.rs index 69eee855e75..7b958b98b41 100644 --- a/src/test/ui/async-await/move-part-await-return-rest-tuple.rs +++ b/src/test/ui/async-await/move-part-await-return-rest-tuple.rs @@ -2,8 +2,6 @@ // edition:2018 // compile-flags: --crate-type lib -#![feature(async_await)] - async fn move_part_await_return_rest_tuple() -> Vec<usize> { let x = (vec![3], vec![4, 4]); drop(x.1); diff --git a/src/test/ui/async-await/multiple-lifetimes/elided.rs b/src/test/ui/async-await/multiple-lifetimes/elided.rs index 45f3170d4c3..8258e2eff52 100644 --- a/src/test/ui/async-await/multiple-lifetimes/elided.rs +++ b/src/test/ui/async-await/multiple-lifetimes/elided.rs @@ -3,8 +3,6 @@ // Test that we can use async fns with multiple arbitrary lifetimes. -#![feature(async_await)] - async fn multiple_elided_lifetimes(_: &u8, _: &u8) {} fn main() { diff --git a/src/test/ui/async-await/multiple-lifetimes/fn-ptr.rs b/src/test/ui/async-await/multiple-lifetimes/fn-ptr.rs index a7254cee755..3912b854747 100644 --- a/src/test/ui/async-await/multiple-lifetimes/fn-ptr.rs +++ b/src/test/ui/async-await/multiple-lifetimes/fn-ptr.rs @@ -3,8 +3,6 @@ // Test that we can use async fns with multiple arbitrary lifetimes. -#![feature(async_await)] - async fn multiple_named_lifetimes<'a, 'b>(_: &'a u8, _: &'b u8, _: fn(&u8)) {} fn gimme(_: &u8) { } diff --git a/src/test/ui/async-await/multiple-lifetimes/hrtb.rs b/src/test/ui/async-await/multiple-lifetimes/hrtb.rs index 589e260d084..31d0736ba63 100644 --- a/src/test/ui/async-await/multiple-lifetimes/hrtb.rs +++ b/src/test/ui/async-await/multiple-lifetimes/hrtb.rs @@ -3,9 +3,6 @@ // Test that we can use async fns with multiple arbitrary lifetimes. -#![feature(async_await)] -#![allow(dead_code)] - use std::ops::Add; async fn multiple_hrtb_and_single_named_lifetime_ok<'c>( diff --git a/src/test/ui/async-await/multiple-lifetimes/named.rs b/src/test/ui/async-await/multiple-lifetimes/named.rs index cd479e256b4..e8eb98102f4 100644 --- a/src/test/ui/async-await/multiple-lifetimes/named.rs +++ b/src/test/ui/async-await/multiple-lifetimes/named.rs @@ -3,8 +3,6 @@ // Test that we can use async fns with multiple arbitrary lifetimes. -#![feature(async_await)] - async fn multiple_named_lifetimes<'a, 'b>(_: &'a u8, _: &'b u8) {} fn main() { diff --git a/src/test/ui/async-await/multiple-lifetimes/partial-relation.rs b/src/test/ui/async-await/multiple-lifetimes/partial-relation.rs index 903c43950a5..02b105999f5 100644 --- a/src/test/ui/async-await/multiple-lifetimes/partial-relation.rs +++ b/src/test/ui/async-await/multiple-lifetimes/partial-relation.rs @@ -1,8 +1,6 @@ // edition:2018 // run-pass -#![feature(async_await)] - async fn lotsa_lifetimes<'a, 'b, 'c>(a: &'a u32, b: &'b u32, c: &'c u32) -> (&'a u32, &'b u32) where 'b: 'a { diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-fg.rs b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-fg.rs index 08622311f7b..b901b61aa18 100644 --- a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-fg.rs +++ b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-fg.rs @@ -4,7 +4,7 @@ // Test that a feature gate is needed to use `impl Trait` as the // return type of an async. -#![feature(async_await, member_constraints)] +#![feature(member_constraints)] trait Trait<'a, 'b> { } impl<T> Trait<'_, '_> for T { } diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.rs b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.rs index 08ecea4cc85..2c7a5cd378f 100644 --- a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.rs +++ b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.rs @@ -3,8 +3,6 @@ // Test that a feature gate is needed to use `impl Trait` as the // return type of an async. -#![feature(async_await)] - trait Trait<'a, 'b> { } impl<T> Trait<'_, '_> for T { } diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.stderr b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.stderr index de2c85d772a..59d7728d41c 100644 --- a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.stderr +++ b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-no-fg.stderr @@ -1,5 +1,5 @@ error: ambiguous lifetime bound in `impl Trait` - --> $DIR/ret-impl-trait-no-fg.rs:11:64 + --> $DIR/ret-impl-trait-no-fg.rs:9:64 | LL | async fn async_ret_impl_trait<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> { | ^^^^^^^^^^^^^^^^^^ neither `'a` nor `'b` outlives the other diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.rs b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.rs index e1b71465273..babc90a5e96 100644 --- a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.rs +++ b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.rs @@ -3,7 +3,7 @@ // Test that a feature gate is needed to use `impl Trait` as the // return type of an async. -#![feature(async_await, member_constraints)] +#![feature(member_constraints)] trait Trait<'a> { } impl<T> Trait<'_> for T { } diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-ref.rs b/src/test/ui/async-await/multiple-lifetimes/ret-ref.rs index 98da90161e5..149c020f9cb 100644 --- a/src/test/ui/async-await/multiple-lifetimes/ret-ref.rs +++ b/src/test/ui/async-await/multiple-lifetimes/ret-ref.rs @@ -4,8 +4,6 @@ // function (which takes multiple lifetimes) only returns data from // one of them. -#![feature(async_await)] - async fn multiple_named_lifetimes<'a, 'b>(a: &'a u8, _: &'b u8) -> &'a u8 { a } diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-ref.stderr b/src/test/ui/async-await/multiple-lifetimes/ret-ref.stderr index fe70d35942c..d86e84033b8 100644 --- a/src/test/ui/async-await/multiple-lifetimes/ret-ref.stderr +++ b/src/test/ui/async-await/multiple-lifetimes/ret-ref.stderr @@ -1,5 +1,5 @@ error[E0506]: cannot assign to `a` because it is borrowed - --> $DIR/ret-ref.rs:18:5 + --> $DIR/ret-ref.rs:16:5 | LL | let future = multiple_named_lifetimes(&a, &b); | -- borrow of `a` occurs here @@ -10,7 +10,7 @@ LL | let p = future.await; | ------ borrow later used here error[E0506]: cannot assign to `b` because it is borrowed - --> $DIR/ret-ref.rs:19:5 + --> $DIR/ret-ref.rs:17:5 | LL | let future = multiple_named_lifetimes(&a, &b); | -- borrow of `b` occurs here @@ -21,7 +21,7 @@ LL | let p = future.await; | ------ borrow later used here error[E0506]: cannot assign to `a` because it is borrowed - --> $DIR/ret-ref.rs:30:5 + --> $DIR/ret-ref.rs:28:5 | LL | let future = multiple_named_lifetimes(&a, &b); | -- borrow of `a` occurs here diff --git a/src/test/ui/async-await/multiple-lifetimes/variance.rs b/src/test/ui/async-await/multiple-lifetimes/variance.rs index b52ad17d563..6ed8bef956a 100644 --- a/src/test/ui/async-await/multiple-lifetimes/variance.rs +++ b/src/test/ui/async-await/multiple-lifetimes/variance.rs @@ -4,9 +4,6 @@ // Test for async fn where the parameters have distinct lifetime // parameters that appear in all possible variances. -#![feature(async_await)] - -#[allow(dead_code)] async fn lotsa_lifetimes<'a, 'b, 'c>(_: fn(&'a u8), _: fn(&'b u8) -> &'b u8, _: fn() -> &'c u8) { } fn take_any(_: &u8) { } diff --git a/src/test/ui/async-await/nested-in-impl.rs b/src/test/ui/async-await/nested-in-impl.rs new file mode 100644 index 00000000000..76ed827d597 --- /dev/null +++ b/src/test/ui/async-await/nested-in-impl.rs @@ -0,0 +1,15 @@ +// Test that async fn works when nested inside of +// impls with lifetime parameters. +// +// check-pass +// edition:2018 + +struct Foo<'a>(&'a ()); + +impl<'a> Foo<'a> { + fn test() { + async fn test() {} + } +} + +fn main() { } diff --git a/src/test/ui/async-await/no-args-non-move-async-closure.rs b/src/test/ui/async-await/no-args-non-move-async-closure.rs index 62d4b3fb6f2..0ca50807f26 100644 --- a/src/test/ui/async-await/no-args-non-move-async-closure.rs +++ b/src/test/ui/async-await/no-args-non-move-async-closure.rs @@ -1,6 +1,6 @@ // edition:2018 -#![feature(async_await, async_closure)] +#![feature(async_closure)] fn main() { let _ = async |x: u8| {}; diff --git a/src/test/ui/async-await/no-async-const.rs b/src/test/ui/async-await/no-async-const.rs index 1db314a5aa2..7a6eb498b2e 100644 --- a/src/test/ui/async-await/no-async-const.rs +++ b/src/test/ui/async-await/no-async-const.rs @@ -2,7 +2,5 @@ // edition:2018 // compile-flags: --crate-type lib -#![feature(async_await)] - pub async const fn x() {} //~^ ERROR expected one of `fn` or `unsafe`, found `const` diff --git a/src/test/ui/async-await/no-async-const.stderr b/src/test/ui/async-await/no-async-const.stderr index cdb1c6e2d7b..edbdfb56522 100644 --- a/src/test/ui/async-await/no-async-const.stderr +++ b/src/test/ui/async-await/no-async-const.stderr @@ -1,5 +1,5 @@ error: expected one of `fn` or `unsafe`, found `const` - --> $DIR/no-async-const.rs:7:11 + --> $DIR/no-async-const.rs:5:11 | LL | pub async const fn x() {} | ^^^^^ expected one of `fn` or `unsafe` here diff --git a/src/test/ui/async-await/no-const-async.rs b/src/test/ui/async-await/no-const-async.rs index 9f09d2188c7..bd78a18a40e 100644 --- a/src/test/ui/async-await/no-const-async.rs +++ b/src/test/ui/async-await/no-const-async.rs @@ -2,8 +2,6 @@ // edition:2018 // compile-flags: --crate-type lib -#![feature(async_await)] - pub const async fn x() {} //~^ ERROR expected identifier, found reserved keyword `async` //~^^ expected `:`, found keyword `fn` diff --git a/src/test/ui/async-await/no-const-async.stderr b/src/test/ui/async-await/no-const-async.stderr index 693fbf186f9..6d7df57e7b6 100644 --- a/src/test/ui/async-await/no-const-async.stderr +++ b/src/test/ui/async-await/no-const-async.stderr @@ -1,5 +1,5 @@ error: expected identifier, found reserved keyword `async` - --> $DIR/no-const-async.rs:7:11 + --> $DIR/no-const-async.rs:5:11 | LL | pub const async fn x() {} | ^^^^^ expected identifier, found reserved keyword @@ -9,7 +9,7 @@ LL | pub const r#async fn x() {} | ^^^^^^^ error: expected `:`, found keyword `fn` - --> $DIR/no-const-async.rs:7:17 + --> $DIR/no-const-async.rs:5:17 | LL | pub const async fn x() {} | ^^ expected `:` diff --git a/src/test/ui/async-await/no-move-across-await-struct.rs b/src/test/ui/async-await/no-move-across-await-struct.rs index 58e09470897..bef477bd256 100644 --- a/src/test/ui/async-await/no-move-across-await-struct.rs +++ b/src/test/ui/async-await/no-move-across-await-struct.rs @@ -2,8 +2,6 @@ // edition:2018 // compile-flags: --crate-type lib -#![feature(async_await)] - async fn no_move_across_await_struct() -> Vec<usize> { let s = Small { x: vec![31], y: vec![19, 1441] }; needs_vec(s.x).await; diff --git a/src/test/ui/async-await/no-move-across-await-struct.stderr b/src/test/ui/async-await/no-move-across-await-struct.stderr index 121c7791bd9..88f147b8d9d 100644 --- a/src/test/ui/async-await/no-move-across-await-struct.stderr +++ b/src/test/ui/async-await/no-move-across-await-struct.stderr @@ -1,5 +1,5 @@ error[E0382]: use of moved value: `s.x` - --> $DIR/no-move-across-await-struct.rs:10:5 + --> $DIR/no-move-across-await-struct.rs:8:5 | LL | needs_vec(s.x).await; | --- value moved here diff --git a/src/test/ui/async-await/no-move-across-await-tuple.rs b/src/test/ui/async-await/no-move-across-await-tuple.rs index 5d3ed3da1e3..565cbd7d5f4 100644 --- a/src/test/ui/async-await/no-move-across-await-tuple.rs +++ b/src/test/ui/async-await/no-move-across-await-tuple.rs @@ -2,8 +2,6 @@ // edition:2018 // compile-flags: --crate-type lib -#![feature(async_await)] - async fn no_move_across_await_tuple() -> Vec<usize> { let x = (vec![3], vec![4, 4]); drop(x.1); diff --git a/src/test/ui/async-await/no-move-across-await-tuple.stderr b/src/test/ui/async-await/no-move-across-await-tuple.stderr index 5da037ea5c0..fe98ecd599a 100644 --- a/src/test/ui/async-await/no-move-across-await-tuple.stderr +++ b/src/test/ui/async-await/no-move-across-await-tuple.stderr @@ -1,5 +1,5 @@ error[E0382]: use of moved value: `x.1` - --> $DIR/no-move-across-await-tuple.rs:11:5 + --> $DIR/no-move-across-await-tuple.rs:9:5 | LL | drop(x.1); | --- value moved here diff --git a/src/test/ui/async-await/no-non-guaranteed-initialization.rs b/src/test/ui/async-await/no-non-guaranteed-initialization.rs index a916afb6b09..0afbf4cee1d 100644 --- a/src/test/ui/async-await/no-non-guaranteed-initialization.rs +++ b/src/test/ui/async-await/no-non-guaranteed-initialization.rs @@ -2,8 +2,6 @@ // edition:2018 // compile-flags: --crate-type lib -#![feature(async_await)] - async fn no_non_guaranteed_initialization(x: usize) -> usize { let y; if x > 5 { diff --git a/src/test/ui/async-await/no-non-guaranteed-initialization.stderr b/src/test/ui/async-await/no-non-guaranteed-initialization.stderr index fb94522cac0..91d7994654f 100644 --- a/src/test/ui/async-await/no-non-guaranteed-initialization.stderr +++ b/src/test/ui/async-await/no-non-guaranteed-initialization.stderr @@ -1,5 +1,5 @@ error[E0381]: use of possibly uninitialized variable: `y` - --> $DIR/no-non-guaranteed-initialization.rs:12:5 + --> $DIR/no-non-guaranteed-initialization.rs:10:5 | LL | y | ^ use of possibly uninitialized `y` diff --git a/src/test/ui/async-await/partial-initialization-across-await.rs b/src/test/ui/async-await/partial-initialization-across-await.rs index 40f9f5202e7..1785fb7f299 100644 --- a/src/test/ui/async-await/partial-initialization-across-await.rs +++ b/src/test/ui/async-await/partial-initialization-across-await.rs @@ -3,8 +3,6 @@ // edition:2018 -#![feature(async_await)] - struct S { x: i32, y: i32 } struct T(i32, i32); diff --git a/src/test/ui/async-await/partial-initialization-across-await.stderr b/src/test/ui/async-await/partial-initialization-across-await.stderr index fe79eb08bef..d9a2db985e5 100644 --- a/src/test/ui/async-await/partial-initialization-across-await.stderr +++ b/src/test/ui/async-await/partial-initialization-across-await.stderr @@ -1,17 +1,17 @@ error[E0381]: assign to part of possibly uninitialized variable: `t` - --> $DIR/partial-initialization-across-await.rs:15:5 + --> $DIR/partial-initialization-across-await.rs:13:5 | LL | t.0 = 42; | ^^^^^^^^ use of possibly uninitialized `t` error[E0381]: assign to part of possibly uninitialized variable: `t` - --> $DIR/partial-initialization-across-await.rs:24:5 + --> $DIR/partial-initialization-across-await.rs:22:5 | LL | t.0 = 42; | ^^^^^^^^ use of possibly uninitialized `t` error[E0381]: assign to part of possibly uninitialized variable: `t` - --> $DIR/partial-initialization-across-await.rs:33:5 + --> $DIR/partial-initialization-across-await.rs:31:5 | LL | t.x = 42; | ^^^^^^^^ use of possibly uninitialized `t` diff --git a/src/test/ui/async-await/recursive-async-impl-trait-type.rs b/src/test/ui/async-await/recursive-async-impl-trait-type.rs index 54f3339870b..aa773319458 100644 --- a/src/test/ui/async-await/recursive-async-impl-trait-type.rs +++ b/src/test/ui/async-await/recursive-async-impl-trait-type.rs @@ -2,8 +2,6 @@ // Test that impl trait does not allow creating recursive types that are // otherwise forbidden when using `async` and `await`. -#![feature(async_await)] - async fn recursive_async_function() -> () { //~ ERROR recursive_async_function().await; } diff --git a/src/test/ui/async-await/recursive-async-impl-trait-type.stderr b/src/test/ui/async-await/recursive-async-impl-trait-type.stderr index 64f6eccd547..8781a9c444d 100644 --- a/src/test/ui/async-await/recursive-async-impl-trait-type.stderr +++ b/src/test/ui/async-await/recursive-async-impl-trait-type.stderr @@ -1,5 +1,5 @@ error[E0733]: recursion in an `async fn` requires boxing - --> $DIR/recursive-async-impl-trait-type.rs:7:40 + --> $DIR/recursive-async-impl-trait-type.rs:5:40 | LL | async fn recursive_async_function() -> () { | ^^ an `async fn` cannot invoke itself directly diff --git a/src/test/ui/async-await/suggest-missing-await-closure.fixed b/src/test/ui/async-await/suggest-missing-await-closure.fixed index 60c9a8581ac..37b30ffe680 100644 --- a/src/test/ui/async-await/suggest-missing-await-closure.fixed +++ b/src/test/ui/async-await/suggest-missing-await-closure.fixed @@ -1,7 +1,7 @@ // edition:2018 // run-rustfix -#![feature(async_await, async_closure)] +#![feature(async_closure)] fn take_u32(_x: u32) {} diff --git a/src/test/ui/async-await/suggest-missing-await-closure.rs b/src/test/ui/async-await/suggest-missing-await-closure.rs index cb992a27bc1..18076a15161 100644 --- a/src/test/ui/async-await/suggest-missing-await-closure.rs +++ b/src/test/ui/async-await/suggest-missing-await-closure.rs @@ -1,7 +1,7 @@ // edition:2018 // run-rustfix -#![feature(async_await, async_closure)] +#![feature(async_closure)] fn take_u32(_x: u32) {} diff --git a/src/test/ui/async-await/suggest-missing-await.fixed b/src/test/ui/async-await/suggest-missing-await.fixed index aa032682be8..7c02a907ce7 100644 --- a/src/test/ui/async-await/suggest-missing-await.fixed +++ b/src/test/ui/async-await/suggest-missing-await.fixed @@ -1,8 +1,6 @@ // edition:2018 // run-rustfix -#![feature(async_await)] - fn take_u32(_x: u32) {} async fn make_u32() -> u32 { diff --git a/src/test/ui/async-await/suggest-missing-await.rs b/src/test/ui/async-await/suggest-missing-await.rs index 2ca814fbb22..91abd44e65c 100644 --- a/src/test/ui/async-await/suggest-missing-await.rs +++ b/src/test/ui/async-await/suggest-missing-await.rs @@ -1,8 +1,6 @@ // edition:2018 // run-rustfix -#![feature(async_await)] - fn take_u32(_x: u32) {} async fn make_u32() -> u32 { diff --git a/src/test/ui/async-await/suggest-missing-await.stderr b/src/test/ui/async-await/suggest-missing-await.stderr index 9bae7150276..ccca97ec204 100644 --- a/src/test/ui/async-await/suggest-missing-await.stderr +++ b/src/test/ui/async-await/suggest-missing-await.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/suggest-missing-await.rs:15:14 + --> $DIR/suggest-missing-await.rs:13:14 | LL | take_u32(x) | ^ diff --git a/src/test/ui/async-await/suggest-switching-edition-on-await.rs b/src/test/ui/async-await/suggest-switching-edition-on-await.rs new file mode 100644 index 00000000000..1402f1ca92b --- /dev/null +++ b/src/test/ui/async-await/suggest-switching-edition-on-await.rs @@ -0,0 +1,45 @@ +use std::pin::Pin; +use std::future::Future; + +fn main() {} + +fn await_on_struct_missing() { + struct S; + let x = S; + x.await; + //~^ ERROR no field `await` on type + //~| NOTE unknown field + //~| NOTE to `.await` a `Future`, switch to Rust 2018 + //~| HELP set `edition = "2018"` in `Cargo.toml` + //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide +} + +fn await_on_struct_similar() { + struct S { + awai: u8, + } + let x = S { awai: 42 }; + x.await; + //~^ ERROR no field `await` on type + //~| HELP a field with a similar name exists + //~| NOTE to `.await` a `Future`, switch to Rust 2018 + //~| HELP set `edition = "2018"` in `Cargo.toml` + //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide +} + +fn await_on_63533(x: Pin<&mut dyn Future<Output = ()>>) { + x.await; + //~^ ERROR no field `await` on type + //~| NOTE unknown field + //~| NOTE to `.await` a `Future`, switch to Rust 2018 + //~| HELP set `edition = "2018"` in `Cargo.toml` + //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide +} + +fn await_on_apit(x: impl Future<Output = ()>) { + x.await; + //~^ ERROR no field `await` on type + //~| NOTE to `.await` a `Future`, switch to Rust 2018 + //~| HELP set `edition = "2018"` in `Cargo.toml` + //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide +} diff --git a/src/test/ui/async-await/suggest-switching-edition-on-await.stderr b/src/test/ui/async-await/suggest-switching-edition-on-await.stderr new file mode 100644 index 00000000000..f623511c0eb --- /dev/null +++ b/src/test/ui/async-await/suggest-switching-edition-on-await.stderr @@ -0,0 +1,43 @@ +error[E0609]: no field `await` on type `await_on_struct_missing::S` + --> $DIR/suggest-switching-edition-on-await.rs:9:7 + | +LL | x.await; + | ^^^^^ unknown field + | + = note: to `.await` a `Future`, switch to Rust 2018 + = help: set `edition = "2018"` in `Cargo.toml` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0609]: no field `await` on type `await_on_struct_similar::S` + --> $DIR/suggest-switching-edition-on-await.rs:22:7 + | +LL | x.await; + | ^^^^^ help: a field with a similar name exists: `awai` + | + = note: to `.await` a `Future`, switch to Rust 2018 + = help: set `edition = "2018"` in `Cargo.toml` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0609]: no field `await` on type `std::pin::Pin<&mut dyn std::future::Future<Output = ()>>` + --> $DIR/suggest-switching-edition-on-await.rs:31:7 + | +LL | x.await; + | ^^^^^ unknown field + | + = note: to `.await` a `Future`, switch to Rust 2018 + = help: set `edition = "2018"` in `Cargo.toml` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0609]: no field `await` on type `impl Future<Output = ()>` + --> $DIR/suggest-switching-edition-on-await.rs:40:7 + | +LL | x.await; + | ^^^^^ + | + = note: to `.await` a `Future`, switch to Rust 2018 + = help: set `edition = "2018"` in `Cargo.toml` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0609`. diff --git a/src/test/ui/async-await/unresolved_type_param.rs b/src/test/ui/async-await/unresolved_type_param.rs index 578d41fe0df..d8ea87d2775 100644 --- a/src/test/ui/async-await/unresolved_type_param.rs +++ b/src/test/ui/async-await/unresolved_type_param.rs @@ -2,7 +2,7 @@ // Error message should pinpoint the type parameter T as needing to be bound // (rather than give a general error message) // edition:2018 -#![feature(async_await)] + async fn bar<T>() -> () {} async fn foo() { diff --git a/src/test/ui/block-expr-precedence.stderr b/src/test/ui/block-expr-precedence.stderr new file mode 100644 index 00000000000..1307b5d6ddd --- /dev/null +++ b/src/test/ui/block-expr-precedence.stderr @@ -0,0 +1,8 @@ +warning: unnecessary trailing semicolons + --> $DIR/block-expr-precedence.rs:60:21 + | +LL | if (true) { 12; };;; -num; + | ^^ help: remove these semicolons + | + = note: `#[warn(redundant_semicolon)]` on by default + diff --git a/src/test/ui/c-variadic/variadic-ffi-no-fixed-args.rs b/src/test/ui/c-variadic/variadic-ffi-no-fixed-args.rs new file mode 100644 index 00000000000..e3b642a9d41 --- /dev/null +++ b/src/test/ui/c-variadic/variadic-ffi-no-fixed-args.rs @@ -0,0 +1,6 @@ +extern { + fn foo(...); + //~^ ERROR C-variadic function must be declared with at least one named argument +} + +fn main() {} diff --git a/src/test/ui/c-variadic/variadic-ffi-no-fixed-args.stderr b/src/test/ui/c-variadic/variadic-ffi-no-fixed-args.stderr new file mode 100644 index 00000000000..cb6060525fc --- /dev/null +++ b/src/test/ui/c-variadic/variadic-ffi-no-fixed-args.stderr @@ -0,0 +1,8 @@ +error: C-variadic function must be declared with at least one named argument + --> $DIR/variadic-ffi-no-fixed-args.rs:2:11 + | +LL | fn foo(...); + | ^ + +error: aborting due to previous error + diff --git a/src/test/ui/const-generics/issue-61432.rs b/src/test/ui/const-generics/issue-61432.rs new file mode 100644 index 00000000000..832095ce542 --- /dev/null +++ b/src/test/ui/const-generics/issue-61432.rs @@ -0,0 +1,17 @@ +// run-pass + +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +fn promote<const N: i32>() { + // works: + // + // let n = N; + // &n; + + &N; +} + +fn main() { + promote::<0>(); +} diff --git a/src/test/ui/const-generics/issue-61432.stderr b/src/test/ui/const-generics/issue-61432.stderr new file mode 100644 index 00000000000..33f77b02810 --- /dev/null +++ b/src/test/ui/const-generics/issue-61432.stderr @@ -0,0 +1,8 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/issue-61432.rs:3:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + diff --git a/src/test/ui/consts/auxiliary/issue-63226.rs b/src/test/ui/consts/auxiliary/issue-63226.rs new file mode 100644 index 00000000000..39cc01a415e --- /dev/null +++ b/src/test/ui/consts/auxiliary/issue-63226.rs @@ -0,0 +1,14 @@ +pub struct VTable{ + state:extern fn(), +} + +impl VTable{ + pub const fn vtable()->&'static VTable{ + Self::VTABLE + } + + const VTABLE: &'static VTable = + &VTable{state}; +} + +extern fn state() {} diff --git a/src/test/ui/consts/const-eval/ub-nonnull.rs b/src/test/ui/consts/const-eval/ub-nonnull.rs index bcbb4358aec..9edae1965ce 100644 --- a/src/test/ui/consts/const-eval/ub-nonnull.rs +++ b/src/test/ui/consts/const-eval/ub-nonnull.rs @@ -1,5 +1,5 @@ #![feature(rustc_attrs, const_transmute)] -#![allow(const_err)] // make sure we cannot allow away the errors tested here +#![allow(const_err, invalid_value)] // make sure we cannot allow away the errors tested here use std::mem; use std::ptr::NonNull; @@ -11,10 +11,11 @@ const NON_NULL_PTR: NonNull<u8> = unsafe { mem::transmute(&1) }; const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) }; //~^ ERROR it is undefined behavior to use this value +#[deny(const_err)] // this triggers a `const_err` so validation does not even happen const OUT_OF_BOUNDS_PTR: NonNull<u8> = { unsafe { -//~^ ERROR it is undefined behavior to use this value - let ptr: &(u8, u8, u8) = mem::transmute(&0u8); // &0 gets promoted so it does not dangle - let out_of_bounds_ptr = &ptr.2; // use address-of-field for pointer arithmetic + let ptr: &[u8; 256] = mem::transmute(&0u8); // &0 gets promoted so it does not dangle + // Use address-of-element for pointer arithmetic. This could wrap around to NULL! + let out_of_bounds_ptr = &ptr[255]; //~ ERROR any use of this value will cause an error mem::transmute(out_of_bounds_ptr) } }; diff --git a/src/test/ui/consts/const-eval/ub-nonnull.stderr b/src/test/ui/consts/const-eval/ub-nonnull.stderr index 2f9423fed35..7b3c97e5fbf 100644 --- a/src/test/ui/consts/const-eval/ub-nonnull.stderr +++ b/src/test/ui/consts/const-eval/ub-nonnull.stderr @@ -6,21 +6,26 @@ LL | const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) }; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior -error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-nonnull.rs:14:1 +error: any use of this value will cause an error + --> $DIR/ub-nonnull.rs:18:29 | LL | / const OUT_OF_BOUNDS_PTR: NonNull<u8> = { unsafe { -LL | | -LL | | let ptr: &(u8, u8, u8) = mem::transmute(&0u8); // &0 gets promoted so it does not dangle -LL | | let out_of_bounds_ptr = &ptr.2; // use address-of-field for pointer arithmetic +LL | | let ptr: &[u8; 256] = mem::transmute(&0u8); // &0 gets promoted so it does not dangle +LL | | // Use address-of-element for pointer arithmetic. This could wrap around to NULL! +LL | | let out_of_bounds_ptr = &ptr[255]; + | | ^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset 256, but is outside bounds of allocation 6 which has size 1 LL | | mem::transmute(out_of_bounds_ptr) LL | | } }; - | |____^ type validation failed: encountered a potentially NULL pointer, but expected something that cannot possibly fail to be greater or equal to 1 + | |____- | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior +note: lint level defined here + --> $DIR/ub-nonnull.rs:14:8 + | +LL | #[deny(const_err)] // this triggers a `const_err` so validation does not even happen + | ^^^^^^^^^ error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-nonnull.rs:21:1 + --> $DIR/ub-nonnull.rs:22:1 | LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1 @@ -28,7 +33,7 @@ LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-nonnull.rs:23:1 + --> $DIR/ub-nonnull.rs:24:1 | LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1 @@ -36,7 +41,7 @@ LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-nonnull.rs:30:1 + --> $DIR/ub-nonnull.rs:31:1 | LL | const UNINIT: NonZeroU8 = unsafe { Transmute { uninit: () }.out }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected something greater or equal to 1 @@ -44,7 +49,7 @@ LL | const UNINIT: NonZeroU8 = unsafe { Transmute { uninit: () }.out }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-nonnull.rs:38:1 + --> $DIR/ub-nonnull.rs:39:1 | LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 42, but expected something in the range 10..=30 @@ -52,7 +57,7 @@ LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-nonnull.rs:44:1 + --> $DIR/ub-nonnull.rs:45:1 | LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 20, but expected something less or equal to 10, or greater or equal to 30 diff --git a/src/test/ui/consts/const-eval/ub-ref.rs b/src/test/ui/consts/const-eval/ub-ref.rs index 0d8f30159b3..bbab85c2121 100644 --- a/src/test/ui/consts/const-eval/ub-ref.rs +++ b/src/test/ui/consts/const-eval/ub-ref.rs @@ -1,6 +1,6 @@ // ignore-tidy-linelength #![feature(const_transmute)] -#![allow(const_err)] // make sure we cannot allow away the errors tested here +#![allow(const_err, invalid_value)] // make sure we cannot allow away the errors tested here use std::mem; diff --git a/src/test/ui/consts/const-eval/ub-upvars.rs b/src/test/ui/consts/const-eval/ub-upvars.rs index 0a427cd8857..baab14dc161 100644 --- a/src/test/ui/consts/const-eval/ub-upvars.rs +++ b/src/test/ui/consts/const-eval/ub-upvars.rs @@ -1,5 +1,5 @@ #![feature(const_transmute)] -#![allow(const_err)] // make sure we cannot allow away the errors tested here +#![allow(const_err, invalid_value)] // make sure we cannot allow away the errors tested here use std::mem; diff --git a/src/test/ui/consts/issue-63226.rs b/src/test/ui/consts/issue-63226.rs new file mode 100644 index 00000000000..deec4499008 --- /dev/null +++ b/src/test/ui/consts/issue-63226.rs @@ -0,0 +1,12 @@ +// aux-build:issue-63226.rs +// compile-flags:--extern issue_63226 +// edition:2018 +// build-pass +// A regression test for issue #63226. +// Checks if `const fn` is marked as reachable. + +use issue_63226::VTable; + +static ICE_ICE:&'static VTable=VTable::vtable(); + +fn main() {} diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.rs b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.rs new file mode 100644 index 00000000000..4281874a031 --- /dev/null +++ b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.rs @@ -0,0 +1,16 @@ +const fn bad_const_fn_deref_raw(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ is unsafe +//~^ dereferencing raw pointers in constant functions + +const unsafe fn bad_const_unsafe_deref_raw(x: *mut usize) -> usize { *x } +//~^ dereferencing raw pointers in constant functions + +const unsafe fn bad_const_unsafe_deref_raw_ref(x: *mut usize) -> &'static usize { &*x } +//~^ dereferencing raw pointers in constant functions + +fn main() {} + +const unsafe fn no_union() { + union Foo { x: (), y: () } + Foo { x: () }.y + //~^ unions in const fn +} diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.stderr index d3f2ece1f92..9de0e732f33 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.stderr @@ -1,5 +1,5 @@ error[E0658]: dereferencing raw pointers in constant functions is unstable - --> $DIR/min_const_fn_unsafe.rs:50:77 + --> $DIR/min_const_fn_unsafe_bad.rs:1:77 | LL | const fn bad_const_fn_deref_raw(x: *mut usize) -> &'static usize { unsafe { &*x } } | ^^^ @@ -8,7 +8,7 @@ LL | const fn bad_const_fn_deref_raw(x: *mut usize) -> &'static usize { unsafe { = help: add `#![feature(const_raw_ptr_deref)]` to the crate attributes to enable error[E0658]: dereferencing raw pointers in constant functions is unstable - --> $DIR/min_const_fn_unsafe.rs:53:70 + --> $DIR/min_const_fn_unsafe_bad.rs:4:70 | LL | const unsafe fn bad_const_unsafe_deref_raw(x: *mut usize) -> usize { *x } | ^^ @@ -17,7 +17,7 @@ LL | const unsafe fn bad_const_unsafe_deref_raw(x: *mut usize) -> usize { *x } = help: add `#![feature(const_raw_ptr_deref)]` to the crate attributes to enable error[E0658]: dereferencing raw pointers in constant functions is unstable - --> $DIR/min_const_fn_unsafe.rs:56:83 + --> $DIR/min_const_fn_unsafe_bad.rs:7:83 | LL | const unsafe fn bad_const_unsafe_deref_raw_ref(x: *mut usize) -> &'static usize { &*x } | ^^^ @@ -26,7 +26,7 @@ LL | const unsafe fn bad_const_unsafe_deref_raw_ref(x: *mut usize) -> &'static u = help: add `#![feature(const_raw_ptr_deref)]` to the crate attributes to enable error[E0658]: unions in const fn are unstable - --> $DIR/min_const_fn_unsafe.rs:63:5 + --> $DIR/min_const_fn_unsafe_bad.rs:14:5 | LL | Foo { x: () }.y | ^^^^^^^^^^^^^^^ @@ -35,7 +35,7 @@ LL | Foo { x: () }.y = help: add `#![feature(const_fn_union)]` to the crate attributes to enable error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block - --> $DIR/min_const_fn_unsafe.rs:50:77 + --> $DIR/min_const_fn_unsafe_bad.rs:1:77 | LL | const fn bad_const_fn_deref_raw(x: *mut usize) -> &'static usize { unsafe { &*x } } | ^^^ dereference of raw pointer diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_ok.rs index 0152561aefc..02c7970deca 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs +++ b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_ok.rs @@ -1,6 +1,4 @@ -//------------------------------------------------------------------------------ -// OK -//------------------------------------------------------------------------------ +// check-pass const unsafe fn ret_i32_no_unsafe() -> i32 { 42 } const unsafe fn ret_null_ptr_no_unsafe<T>() -> *const T { std::ptr::null() } @@ -43,23 +41,4 @@ const unsafe fn call_unsafe_generic_cell_const_unsafe_fn_immediate() ret_null_mut_ptr_no_unsafe::<Vec<std::cell::Cell<u32>>>() } -//------------------------------------------------------------------------------ -// NOT OK -//------------------------------------------------------------------------------ - -const fn bad_const_fn_deref_raw(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ is unsafe -//~^ dereferencing raw pointers in constant functions - -const unsafe fn bad_const_unsafe_deref_raw(x: *mut usize) -> usize { *x } -//~^ dereferencing raw pointers in constant functions - -const unsafe fn bad_const_unsafe_deref_raw_ref(x: *mut usize) -> &'static usize { &*x } -//~^ dereferencing raw pointers in constant functions - fn main() {} - -const unsafe fn no_union() { - union Foo { x: (), y: () } - Foo { x: () }.y - //~^ unions in const fn -} diff --git a/src/test/ui/consts/too_generic_eval_ice.rs b/src/test/ui/consts/too_generic_eval_ice.rs new file mode 100644 index 00000000000..7a299169bc4 --- /dev/null +++ b/src/test/ui/consts/too_generic_eval_ice.rs @@ -0,0 +1,13 @@ +pub struct Foo<A, B>(A, B); + +impl<A, B> Foo<A, B> { + const HOST_SIZE: usize = std::mem::size_of::<B>(); + + pub fn crash() -> bool { + [5; Self::HOST_SIZE] == [6; 0] //~ ERROR no associated item named `HOST_SIZE` + //~^ the size for values of type `A` cannot be known + //~| the size for values of type `B` cannot be known + } +} + +fn main() {} diff --git a/src/test/ui/consts/too_generic_eval_ice.stderr b/src/test/ui/consts/too_generic_eval_ice.stderr new file mode 100644 index 00000000000..eef79421270 --- /dev/null +++ b/src/test/ui/consts/too_generic_eval_ice.stderr @@ -0,0 +1,47 @@ +error[E0599]: no associated item named `HOST_SIZE` found for type `Foo<A, B>` in the current scope + --> $DIR/too_generic_eval_ice.rs:7:19 + | +LL | pub struct Foo<A, B>(A, B); + | --------------------------- associated item `HOST_SIZE` not found for this +... +LL | [5; Self::HOST_SIZE] == [6; 0] + | ^^^^^^^^^ associated item not found in `Foo<A, B>` + | + = note: the method `HOST_SIZE` exists but the following trait bounds were not satisfied: + `A : std::marker::Sized` + `B : std::marker::Sized` + +error[E0277]: the size for values of type `A` cannot be known at compilation time + --> $DIR/too_generic_eval_ice.rs:7:13 + | +LL | [5; Self::HOST_SIZE] == [6; 0] + | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `std::marker::Sized` is not implemented for `A` + = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait> + = help: consider adding a `where A: std::marker::Sized` bound +note: required by `Foo` + --> $DIR/too_generic_eval_ice.rs:1:1 + | +LL | pub struct Foo<A, B>(A, B); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: the size for values of type `B` cannot be known at compilation time + --> $DIR/too_generic_eval_ice.rs:7:13 + | +LL | [5; Self::HOST_SIZE] == [6; 0] + | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `std::marker::Sized` is not implemented for `B` + = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait> + = help: consider adding a `where B: std::marker::Sized` bound +note: required by `Foo` + --> $DIR/too_generic_eval_ice.rs:1:1 + | +LL | pub struct Foo<A, B>(A, B); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0277, E0599. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/consts/zst_no_llvm_alloc.rs b/src/test/ui/consts/zst_no_llvm_alloc.rs new file mode 100644 index 00000000000..5d779355400 --- /dev/null +++ b/src/test/ui/consts/zst_no_llvm_alloc.rs @@ -0,0 +1,19 @@ +// run-pass + +#[repr(align(4))] +struct Foo; + +static FOO: Foo = Foo; + +fn main() { + let x: &'static () = &(); + assert_eq!(x as *const () as usize, 1); + let x: &'static Foo = &Foo; + assert_eq!(x as *const Foo as usize, 4); + + // statics must have a unique address + assert_ne!(&FOO as *const Foo as usize, 4); + + assert_eq!(<Vec<i32>>::new().as_ptr(), <&[i32]>::default().as_ptr()); + assert_eq!(<Box<[i32]>>::default().as_ptr(), (&[]).as_ptr()); +} diff --git a/src/test/ui/derives/derive-hygiene.rs b/src/test/ui/derives/derive-hygiene.rs new file mode 100644 index 00000000000..4fa83c49038 --- /dev/null +++ b/src/test/ui/derives/derive-hygiene.rs @@ -0,0 +1,121 @@ +// Make sure that built-in derives don't rely on the user not declaring certain +// names to work properly. + +// check-pass + +#![allow(nonstandard_style)] +#![feature(decl_macro)] + +use std::prelude::v1::test as inline; + +static f: () = (); +static cmp: () = (); +static other: () = (); +static state: () = (); +static __self_0_0: () = (); +static __self_1_0: () = (); +static __self_vi: () = (); +static __arg_1_0: () = (); +static debug_trait_builder: () = (); + +struct isize; +trait i16 {} + +trait MethodsInDerives: Sized { + fn debug_tuple(self) {} + fn debug_struct(self) {} + fn field(self) {} + fn finish(self) {} + fn clone(self) {} + fn cmp(self) {} + fn partial_cmp(self) {} + fn eq(self) {} + fn ne(self) {} + fn le(self) {} + fn lt(self) {} + fn ge(self) {} + fn gt(self) {} + fn hash(self) {} +} + +trait GenericAny<T, U> {} +impl<S, T, U> GenericAny<T, U> for S {} + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] +enum __H { V(i32), } + +#[repr(i16)] +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] +enum W { A, B } + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Default, Hash)] +struct X<A: GenericAny<A, self::X<i32>>> { + A: A, +} + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Default, Hash)] +struct Y<B>(B) +where + B: From<B>; + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] +enum Z<C> { + C(C), + B { C: C }, +} + +// Make sure that we aren't using `self::` in paths, since it doesn't work in +// non-module scopes. +const NON_MODULE: () = { + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] + enum __H { V(i32), } + + #[repr(i16)] + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] + enum W { A, B } + + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Default, Hash)] + struct X<A: Fn(A) -> self::X<i32>> { + A: A, + } + + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Default, Hash)] + struct Y<B>(B) + where + B: From<B>; + + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] + enum Z<C> { + C(C), + B { C: C }, + } +}; + +macro m() { + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] + enum __H { V(i32), } + + #[repr(i16)] + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] + enum W { A, B } + + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Default, Hash)] + struct X<A: GenericAny<A, self::X<i32>>> { + A: A, + } + + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Default, Hash)] + struct Y<B>(B) + where + B: From<B>; + + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] + enum Z<C> { + C(C), + B { C: C }, + } +} + +m!(); + +fn main() {} diff --git a/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr b/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr index f1c93d54637..f5edbe2a3af 100644 --- a/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr +++ b/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr @@ -28,7 +28,10 @@ error: expected `{`, found `;` LL | if not // lack of braces is [sic] | -- this `if` statement has a condition, but no block LL | println!("Then when?"); - | ^ expected `{` + | ^ + | | + | expected `{` + | help: try placing this code inside a block: `{ ; }` error: unexpected `2` after identifier --> $DIR/issue-46836-identifier-not-instead-of-negation.rs:26:24 diff --git a/src/test/ui/drop/dynamic-drop-async.rs b/src/test/ui/drop/dynamic-drop-async.rs index f3f5c382275..79d09d18176 100644 --- a/src/test/ui/drop/dynamic-drop-async.rs +++ b/src/test/ui/drop/dynamic-drop-async.rs @@ -7,10 +7,7 @@ // edition:2018 // ignore-wasm32-bare compiled with panic=abort by default -#![allow(unused_assignments)] -#![allow(unused_variables)] #![feature(slice_patterns)] -#![feature(async_await)] use std::{ cell::{Cell, RefCell}, diff --git a/src/test/ui/dropck/dropck_trait_cycle_checked.stderr b/src/test/ui/dropck/dropck_trait_cycle_checked.stderr index 1e779208e58..dc3fbed593b 100644 --- a/src/test/ui/dropck/dropck_trait_cycle_checked.stderr +++ b/src/test/ui/dropck/dropck_trait_cycle_checked.stderr @@ -2,7 +2,7 @@ error[E0597]: `o2` does not live long enough --> $DIR/dropck_trait_cycle_checked.rs:111:13 | LL | let (o1, o2, o3): (Box<dyn Obj>, Box<dyn Obj>, Box<dyn Obj>) = (O::new(), O::new(), O::new()); - | -------- cast requires that `o2` is borrowed for `'static` + | -------- cast requires that `o2` is borrowed for `'static` LL | o1.set0(&o2); | ^^^ borrowed value does not live long enough ... @@ -13,7 +13,7 @@ error[E0597]: `o3` does not live long enough --> $DIR/dropck_trait_cycle_checked.rs:112:13 | LL | let (o1, o2, o3): (Box<dyn Obj>, Box<dyn Obj>, Box<dyn Obj>) = (O::new(), O::new(), O::new()); - | -------- cast requires that `o3` is borrowed for `'static` + | -------- cast requires that `o3` is borrowed for `'static` LL | o1.set0(&o2); LL | o1.set1(&o3); | ^^^ borrowed value does not live long enough @@ -37,7 +37,7 @@ error[E0597]: `o3` does not live long enough --> $DIR/dropck_trait_cycle_checked.rs:114:13 | LL | let (o1, o2, o3): (Box<dyn Obj>, Box<dyn Obj>, Box<dyn Obj>) = (O::new(), O::new(), O::new()); - | -------- cast requires that `o3` is borrowed for `'static` + | -------- cast requires that `o3` is borrowed for `'static` ... LL | o2.set1(&o3); | ^^^ borrowed value does not live long enough @@ -49,7 +49,7 @@ error[E0597]: `o1` does not live long enough --> $DIR/dropck_trait_cycle_checked.rs:115:13 | LL | let (o1, o2, o3): (Box<dyn Obj>, Box<dyn Obj>, Box<dyn Obj>) = (O::new(), O::new(), O::new()); - | -------- cast requires that `o1` is borrowed for `'static` + | -------- cast requires that `o1` is borrowed for `'static` ... LL | o3.set0(&o1); | ^^^ borrowed value does not live long enough @@ -61,7 +61,7 @@ error[E0597]: `o2` does not live long enough --> $DIR/dropck_trait_cycle_checked.rs:116:13 | LL | let (o1, o2, o3): (Box<dyn Obj>, Box<dyn Obj>, Box<dyn Obj>) = (O::new(), O::new(), O::new()); - | -------- cast requires that `o2` is borrowed for `'static` + | -------- cast requires that `o2` is borrowed for `'static` ... LL | o3.set1(&o2); | ^^^ borrowed value does not live long enough diff --git a/src/test/ui/duplicate/duplicate-type-parameter.stderr b/src/test/ui/duplicate/duplicate-type-parameter.stderr index 8606479ff68..6754574f0b9 100644 --- a/src/test/ui/duplicate/duplicate-type-parameter.stderr +++ b/src/test/ui/duplicate/duplicate-type-parameter.stderr @@ -1,4 +1,4 @@ -error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters --> $DIR/duplicate-type-parameter.rs:1:12 | LL | type Foo<T,T> = Option<T>; @@ -6,7 +6,7 @@ LL | type Foo<T,T> = Option<T>; | | | first use of `T` -error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters --> $DIR/duplicate-type-parameter.rs:4:14 | LL | struct Bar<T,T>(T); @@ -14,7 +14,7 @@ LL | struct Bar<T,T>(T); | | | first use of `T` -error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters --> $DIR/duplicate-type-parameter.rs:7:14 | LL | struct Baz<T,T> { @@ -22,7 +22,7 @@ LL | struct Baz<T,T> { | | | first use of `T` -error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters --> $DIR/duplicate-type-parameter.rs:12:12 | LL | enum Boo<T,T> { @@ -30,7 +30,7 @@ LL | enum Boo<T,T> { | | | first use of `T` -error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters --> $DIR/duplicate-type-parameter.rs:18:11 | LL | fn quux<T,T>(x: T) {} @@ -38,7 +38,7 @@ LL | fn quux<T,T>(x: T) {} | | | first use of `T` -error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters --> $DIR/duplicate-type-parameter.rs:21:13 | LL | trait Qux<T,T> {} @@ -46,7 +46,7 @@ LL | trait Qux<T,T> {} | | | first use of `T` -error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters --> $DIR/duplicate-type-parameter.rs:24:8 | LL | impl<T,T> Qux<T,T> for Option<T> {} diff --git a/src/test/ui/error-codes/E0194.rs b/src/test/ui/error-codes/E0194.rs index 71eff0e7465..8a43f38fcfd 100644 --- a/src/test/ui/error-codes/E0194.rs +++ b/src/test/ui/error-codes/E0194.rs @@ -1,7 +1,7 @@ trait Foo<T> { fn do_something(&self) -> T; fn do_something_else<T: Clone>(&self, bar: T); - //~^ ERROR E0194 + //~^ ERROR E0403 } fn main() { diff --git a/src/test/ui/error-codes/E0194.stderr b/src/test/ui/error-codes/E0194.stderr index ab4918a4e27..f2c908eea0b 100644 --- a/src/test/ui/error-codes/E0194.stderr +++ b/src/test/ui/error-codes/E0194.stderr @@ -1,12 +1,12 @@ -error[E0194]: type parameter `T` shadows another type parameter of the same name +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters --> $DIR/E0194.rs:3:26 | LL | trait Foo<T> { - | - first `T` declared here + | - first use of `T` LL | fn do_something(&self) -> T; LL | fn do_something_else<T: Clone>(&self, bar: T); - | ^ shadows another type parameter + | ^ already used error: aborting due to previous error -For more information about this error, try `rustc --explain E0194`. +For more information about this error, try `rustc --explain E0403`. diff --git a/src/test/ui/error-codes/E0282.stderr b/src/test/ui/error-codes/E0282.stderr index 3a5040eb6da..0f610a5e42f 100644 --- a/src/test/ui/error-codes/E0282.stderr +++ b/src/test/ui/error-codes/E0282.stderr @@ -2,10 +2,7 @@ error[E0282]: type annotations needed --> $DIR/E0282.rs:2:9 | LL | let x = "hello".chars().rev().collect(); - | ^ - | | - | cannot infer type - | consider giving `x` a type + | ^ consider giving `x` a type error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0403.stderr b/src/test/ui/error-codes/E0403.stderr index 2bd7de6c246..d76a58a7c80 100644 --- a/src/test/ui/error-codes/E0403.stderr +++ b/src/test/ui/error-codes/E0403.stderr @@ -1,4 +1,4 @@ -error[E0403]: the name `T` is already used for a generic parameter in this list of generic parameters +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters --> $DIR/E0403.rs:1:11 | LL | fn foo<T, T>(s: T, u: T) {} diff --git a/src/test/ui/feature-gate/feature-gate-or_patterns.rs b/src/test/ui/feature-gate/feature-gate-or_patterns.rs new file mode 100644 index 00000000000..036a6095965 --- /dev/null +++ b/src/test/ui/feature-gate/feature-gate-or_patterns.rs @@ -0,0 +1,9 @@ +#![crate_type="lib"] + +pub fn example(x: Option<usize>) { + match x { + Some(0 | 1 | 2) => {} + //~^ ERROR: or-patterns syntax is experimental + _ => {} + } +} diff --git a/src/test/ui/feature-gate/feature-gate-or_patterns.stderr b/src/test/ui/feature-gate/feature-gate-or_patterns.stderr new file mode 100644 index 00000000000..aaabb54c1f0 --- /dev/null +++ b/src/test/ui/feature-gate/feature-gate-or_patterns.stderr @@ -0,0 +1,12 @@ +error[E0658]: or-patterns syntax is experimental + --> $DIR/feature-gate-or_patterns.rs:5:14 + | +LL | Some(0 | 1 | 2) => {} + | ^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54883 + = help: add `#![feature(or_patterns)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.rs b/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.rs deleted file mode 100644 index 801aeb82aa2..00000000000 --- a/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.rs +++ /dev/null @@ -1,9 +0,0 @@ -// edition:2015 - -async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition - //~^ ERROR async fn is unstable - -fn main() { - let _ = async {}; //~ ERROR cannot find struct, variant or union type `async` - let _ = async || { true }; //~ ERROR cannot find value `async` in this scope -} diff --git a/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.stderr b/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.stderr deleted file mode 100644 index 0157ed55344..00000000000 --- a/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.stderr +++ /dev/null @@ -1,31 +0,0 @@ -error[E0670]: `async fn` is not permitted in the 2015 edition - --> $DIR/feature-gate-async-await-2015-edition.rs:3:1 - | -LL | async fn foo() {} - | ^^^^^ - -error[E0422]: cannot find struct, variant or union type `async` in this scope - --> $DIR/feature-gate-async-await-2015-edition.rs:7:13 - | -LL | let _ = async {}; - | ^^^^^ not found in this scope - -error[E0425]: cannot find value `async` in this scope - --> $DIR/feature-gate-async-await-2015-edition.rs:8:13 - | -LL | let _ = async || { true }; - | ^^^^^ not found in this scope - -error[E0658]: async fn is unstable - --> $DIR/feature-gate-async-await-2015-edition.rs:3:1 - | -LL | async fn foo() {} - | ^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/50547 - = help: add `#![feature(async_await)]` to the crate attributes to enable - -error: aborting due to 4 previous errors - -Some errors have detailed explanations: E0422, E0425, E0658, E0670. -For more information about an error, try `rustc --explain E0422`. diff --git a/src/test/ui/feature-gates/feature-gate-async-await.rs b/src/test/ui/feature-gates/feature-gate-async-await.rs deleted file mode 100644 index 78391c0e104..00000000000 --- a/src/test/ui/feature-gates/feature-gate-async-await.rs +++ /dev/null @@ -1,18 +0,0 @@ -// edition:2018 - -struct S; - -impl S { - async fn foo() {} //~ ERROR async fn is unstable -} - -trait T { - async fn foo(); //~ ERROR trait fns cannot be declared `async` - //~^ ERROR async fn is unstable -} - -async fn foo() {} //~ ERROR async fn is unstable - -fn main() { - let _ = async {}; //~ ERROR async blocks are unstable -} diff --git a/src/test/ui/feature-gates/feature-gate-async-await.stderr b/src/test/ui/feature-gates/feature-gate-async-await.stderr deleted file mode 100644 index 9f4a90157a4..00000000000 --- a/src/test/ui/feature-gates/feature-gate-async-await.stderr +++ /dev/null @@ -1,45 +0,0 @@ -error[E0706]: trait fns cannot be declared `async` - --> $DIR/feature-gate-async-await.rs:10:5 - | -LL | async fn foo(); - | ^^^^^^^^^^^^^^^ - -error[E0658]: async fn is unstable - --> $DIR/feature-gate-async-await.rs:6:5 - | -LL | async fn foo() {} - | ^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/50547 - = help: add `#![feature(async_await)]` to the crate attributes to enable - -error[E0658]: async fn is unstable - --> $DIR/feature-gate-async-await.rs:10:5 - | -LL | async fn foo(); - | ^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/50547 - = help: add `#![feature(async_await)]` to the crate attributes to enable - -error[E0658]: async fn is unstable - --> $DIR/feature-gate-async-await.rs:14:1 - | -LL | async fn foo() {} - | ^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/50547 - = help: add `#![feature(async_await)]` to the crate attributes to enable - -error[E0658]: async blocks are unstable - --> $DIR/feature-gate-async-await.rs:17:13 - | -LL | let _ = async {}; - | ^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/50547 - = help: add `#![feature(async_await)]` to the crate attributes to enable - -error: aborting due to 5 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-generators.rs b/src/test/ui/feature-gates/feature-gate-generators.rs index cee930fd785..382d891feed 100644 --- a/src/test/ui/feature-gates/feature-gate-generators.rs +++ b/src/test/ui/feature-gates/feature-gate-generators.rs @@ -2,3 +2,9 @@ fn main() { yield true; //~ ERROR yield syntax is experimental //~^ ERROR yield statement outside of generator literal } + +#[cfg(FALSE)] +fn foo() { + yield; //~ ERROR yield syntax is experimental + yield 0; //~ ERROR yield syntax is experimental +} diff --git a/src/test/ui/feature-gates/feature-gate-generators.stderr b/src/test/ui/feature-gates/feature-gate-generators.stderr index cdb05601254..24b814b410c 100644 --- a/src/test/ui/feature-gates/feature-gate-generators.stderr +++ b/src/test/ui/feature-gates/feature-gate-generators.stderr @@ -7,12 +7,30 @@ LL | yield true; = note: for more information, see https://github.com/rust-lang/rust/issues/43122 = help: add `#![feature(generators)]` to the crate attributes to enable +error[E0658]: yield syntax is experimental + --> $DIR/feature-gate-generators.rs:8:5 + | +LL | yield; + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/43122 + = help: add `#![feature(generators)]` to the crate attributes to enable + +error[E0658]: yield syntax is experimental + --> $DIR/feature-gate-generators.rs:9:5 + | +LL | yield 0; + | ^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/43122 + = help: add `#![feature(generators)]` to the crate attributes to enable + error[E0627]: yield statement outside of generator literal --> $DIR/feature-gate-generators.rs:2:5 | LL | yield true; | ^^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-rustc-diagnostic-macros.stderr b/src/test/ui/feature-gates/feature-gate-rustc-diagnostic-macros.stderr index 478bc09f291..676b8b9f056 100644 --- a/src/test/ui/feature-gates/feature-gate-rustc-diagnostic-macros.stderr +++ b/src/test/ui/feature-gates/feature-gate-rustc-diagnostic-macros.stderr @@ -4,17 +4,17 @@ error: cannot find macro `__build_diagnostic_array!` in this scope LL | __build_diagnostic_array!(DIAGNOSTICS); | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: cannot find macro `__register_diagnostic!` in this scope - --> $DIR/feature-gate-rustc-diagnostic-macros.rs:4:1 - | -LL | __register_diagnostic!(E0001); - | ^^^^^^^^^^^^^^^^^^^^^ - error: cannot find macro `__diagnostic_used!` in this scope --> $DIR/feature-gate-rustc-diagnostic-macros.rs:8:5 | LL | __diagnostic_used!(E0001); | ^^^^^^^^^^^^^^^^^ +error: cannot find macro `__register_diagnostic!` in this scope + --> $DIR/feature-gate-rustc-diagnostic-macros.rs:4:1 + | +LL | __register_diagnostic!(E0001); + | ^^^^^^^^^^^^^^^^^^^^^ + error: aborting due to 3 previous errors diff --git a/src/test/ui/for/for-loop-unconstrained-element-type.stderr b/src/test/ui/for/for-loop-unconstrained-element-type.stderr index 02fdb808da4..0672014a929 100644 --- a/src/test/ui/for/for-loop-unconstrained-element-type.stderr +++ b/src/test/ui/for/for-loop-unconstrained-element-type.stderr @@ -2,10 +2,7 @@ error[E0282]: type annotations needed --> $DIR/for-loop-unconstrained-element-type.rs:8:14 | LL | for i in Vec::new() { } - | ^^^^^^^^^^ - | | - | cannot infer type - | the element type for this iterator is not specified + | ^^^^^^^^^^ the element type for this iterator is not specified error: aborting due to previous error diff --git a/src/test/ui/generator/issue-61442-stmt-expr-with-drop.rs b/src/test/ui/generator/issue-61442-stmt-expr-with-drop.rs index ce4642020f0..e3d19029348 100644 --- a/src/test/ui/generator/issue-61442-stmt-expr-with-drop.rs +++ b/src/test/ui/generator/issue-61442-stmt-expr-with-drop.rs @@ -4,7 +4,7 @@ // check-pass // edition:2018 -#![feature(async_await, generators, generator_trait)] +#![feature(generators, generator_trait)] use std::ops::Generator; diff --git a/src/test/ui/generator/issue-62506-two_awaits.rs b/src/test/ui/generator/issue-62506-two_awaits.rs index 774019b6a5b..672e16b780d 100644 --- a/src/test/ui/generator/issue-62506-two_awaits.rs +++ b/src/test/ui/generator/issue-62506-two_awaits.rs @@ -4,7 +4,6 @@ // check-pass // edition:2018 -#![feature(async_await)] use std::future::Future; pub trait T { diff --git a/src/test/run-pass/generator/niche-in-generator.rs b/src/test/ui/generator/niche-in-generator.rs index 9a644ed44a6..42bee81f524 100644 --- a/src/test/run-pass/generator/niche-in-generator.rs +++ b/src/test/ui/generator/niche-in-generator.rs @@ -1,5 +1,7 @@ // Test that niche finding works with captured generator upvars. +// run-pass + #![feature(generators)] use std::mem::size_of_val; diff --git a/src/test/ui/higher-rank-trait-bounds/hrtb-type-outlives.rs b/src/test/ui/higher-rank-trait-bounds/hrtb-type-outlives.rs index a8f38180cc2..88d396101db 100644 --- a/src/test/ui/higher-rank-trait-bounds/hrtb-type-outlives.rs +++ b/src/test/ui/higher-rank-trait-bounds/hrtb-type-outlives.rs @@ -14,7 +14,6 @@ fn want_foo<T>() { } -/////////////////////////////////////////////////////////////////////////// // Expressed as a where clause struct SomeStruct<X> { @@ -30,7 +29,6 @@ fn one() { want_foo::<SomeStruct<usize>>(); } -/////////////////////////////////////////////////////////////////////////// // Expressed as shorthand struct AnotherStruct<X> { diff --git a/src/test/ui/hrtb/hrtb-conflate-regions.rs b/src/test/ui/hrtb/hrtb-conflate-regions.rs index 391303676d7..004d62ac513 100644 --- a/src/test/ui/hrtb/hrtb-conflate-regions.rs +++ b/src/test/ui/hrtb/hrtb-conflate-regions.rs @@ -15,7 +15,6 @@ fn want_foo1<T>() { } -/////////////////////////////////////////////////////////////////////////// // Expressed as a where clause struct SomeStruct; diff --git a/src/test/ui/hrtb/hrtb-conflate-regions.stderr b/src/test/ui/hrtb/hrtb-conflate-regions.stderr index 3fb6baa35e1..20265d66c6f 100644 --- a/src/test/ui/hrtb/hrtb-conflate-regions.stderr +++ b/src/test/ui/hrtb/hrtb-conflate-regions.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `for<'a, 'b> SomeStruct: Foo<(&'a isize, &'b isize)>` is not satisfied - --> $DIR/hrtb-conflate-regions.rs:28:10 + --> $DIR/hrtb-conflate-regions.rs:27:10 | LL | fn b() { want_foo2::<SomeStruct>(); } | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a, 'b> Foo<(&'a isize, &'b isize)>` is not implemented for `SomeStruct` diff --git a/src/test/ui/hygiene/auxiliary/codegen-attrs.rs b/src/test/ui/hygiene/auxiliary/codegen-attrs.rs new file mode 100644 index 00000000000..74afedbeb77 --- /dev/null +++ b/src/test/ui/hygiene/auxiliary/codegen-attrs.rs @@ -0,0 +1,10 @@ +#![feature(decl_macro)] + +macro m($f:ident) { + #[export_name = "export_function_name"] + pub fn $f() -> i32 { + 2 + } +} + +m!(rust_function_name); diff --git a/src/test/ui/hygiene/cross-crate-codegen-attrs.rs b/src/test/ui/hygiene/cross-crate-codegen-attrs.rs new file mode 100644 index 00000000000..af6b1334387 --- /dev/null +++ b/src/test/ui/hygiene/cross-crate-codegen-attrs.rs @@ -0,0 +1,12 @@ +// Make sure that macro expanded codegen attributes work across crates. +// We used to gensym the identifiers in attributes, which stopped dependent +// crates from seeing them, resulting in linker errors in cases like this one. + +// run-pass +// aux-build:codegen-attrs.rs + +extern crate codegen_attrs; + +fn main() { + assert_eq!(codegen_attrs::rust_function_name(), 2); +} diff --git a/src/test/ui/hygiene/no_implicit_prelude.stderr b/src/test/ui/hygiene/no_implicit_prelude.stderr index a89176fe690..643f803f620 100644 --- a/src/test/ui/hygiene/no_implicit_prelude.stderr +++ b/src/test/ui/hygiene/no_implicit_prelude.stderr @@ -1,3 +1,11 @@ +error: cannot find macro `panic!` in this scope + --> $DIR/no_implicit_prelude.rs:16:9 + | +LL | assert_eq!(0, 0); + | ^^^^^^^^^^^^^^^^^ + | + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + error[E0433]: failed to resolve: use of undeclared type or module `Vec` --> $DIR/no_implicit_prelude.rs:11:9 | @@ -7,14 +15,6 @@ LL | fn f() { ::bar::m!(); } LL | Vec::new(); | ^^^ use of undeclared type or module `Vec` -error: cannot find macro `panic!` in this scope - --> $DIR/no_implicit_prelude.rs:16:9 - | -LL | assert_eq!(0, 0); - | ^^^^^^^^^^^^^^^^^ - | - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) - error[E0599]: no method named `clone` found for type `()` in the current scope --> $DIR/no_implicit_prelude.rs:12:12 | diff --git a/src/test/ui/impl-trait/bound-normalization-fail.rs b/src/test/ui/impl-trait/bound-normalization-fail.rs index c33261bfd09..235c1f80ef6 100644 --- a/src/test/ui/impl-trait/bound-normalization-fail.rs +++ b/src/test/ui/impl-trait/bound-normalization-fail.rs @@ -1,13 +1,12 @@ // compile-fail +// ignore-tidy-linelength // edition:2018 -#![feature(async_await)] #![feature(impl_trait_in_bindings)] //~^ WARNING the feature `impl_trait_in_bindings` is incomplete // See issue 60414 -///////////////////////////////////////////// // Reduction to `impl Trait` struct Foo<T>(T); @@ -32,7 +31,6 @@ mod impl_trait { } } -///////////////////////////////////////////// // Same with lifetimes in the trait mod lifetimes { @@ -44,7 +42,8 @@ mod lifetimes { /// Missing bound constraining `Assoc`, `T::Assoc` can't be normalized further. fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike<Output=T::Assoc> { - //~^ ERROR: type mismatch + //~^ ERROR: type mismatch + //~^^ ERROR `impl Trait` return type cannot contain a projection or `Self` that references lifetimes from a parent scope Foo(()) } } diff --git a/src/test/ui/impl-trait/bound-normalization-fail.stderr b/src/test/ui/impl-trait/bound-normalization-fail.stderr index aa306a7e08a..2c4c61a0957 100644 --- a/src/test/ui/impl-trait/bound-normalization-fail.stderr +++ b/src/test/ui/impl-trait/bound-normalization-fail.stderr @@ -7,7 +7,7 @@ LL | #![feature(impl_trait_in_bindings)] = note: `#[warn(incomplete_features)]` on by default error[E0271]: type mismatch resolving `<Foo<()> as FooLike>::Output == <T as impl_trait::Trait>::Assoc` - --> $DIR/bound-normalization-fail.rs:29:32 + --> $DIR/bound-normalization-fail.rs:28:32 | LL | fn foo_fail<T: Trait>() -> impl FooLike<Output=T::Assoc> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found associated type @@ -16,8 +16,14 @@ LL | fn foo_fail<T: Trait>() -> impl FooLike<Output=T::Assoc> { found type `<T as impl_trait::Trait>::Assoc` = note: the return type of a function must have a statically known size +error: `impl Trait` return type cannot contain a projection or `Self` that references lifetimes from a parent scope + --> $DIR/bound-normalization-fail.rs:44:41 + | +LL | fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike<Output=T::Assoc> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error[E0271]: type mismatch resolving `<Foo<()> as FooLike>::Output == <T as lifetimes::Trait<'static>>::Assoc` - --> $DIR/bound-normalization-fail.rs:46:41 + --> $DIR/bound-normalization-fail.rs:44:41 | LL | fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike<Output=T::Assoc> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found associated type @@ -26,6 +32,6 @@ LL | fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike<Output=T::Assoc> { found type `<T as lifetimes::Trait<'static>>::Assoc` = note: the return type of a function must have a statically known size -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0271`. diff --git a/src/test/ui/impl-trait/bound-normalization-pass.rs b/src/test/ui/impl-trait/bound-normalization-pass.rs index 5b634e3106e..fff17667fda 100644 --- a/src/test/ui/impl-trait/bound-normalization-pass.rs +++ b/src/test/ui/impl-trait/bound-normalization-pass.rs @@ -1,14 +1,12 @@ // check-pass // edition:2018 -#![feature(async_await)] #![feature(type_alias_impl_trait)] #![feature(impl_trait_in_bindings)] //~^ WARNING the feature `impl_trait_in_bindings` is incomplete // See issue 60414 -///////////////////////////////////////////// // Reduction to `impl Trait` struct Foo<T>(T); @@ -32,7 +30,6 @@ mod impl_trait { } } -///////////////////////////////////////////// // Same with lifetimes in the trait mod lifetimes { @@ -59,7 +56,6 @@ mod lifetimes { } } -///////////////////////////////////////////// // Reduction using `impl Trait` in bindings mod impl_trait_in_bindings { @@ -80,7 +76,6 @@ mod impl_trait_in_bindings { } } -///////////////////////////////////////////// // The same applied to `type Foo = impl Bar`s mod opaque_types { diff --git a/src/test/ui/impl-trait/bound-normalization-pass.stderr b/src/test/ui/impl-trait/bound-normalization-pass.stderr index 229acdb2b14..d048da7f60b 100644 --- a/src/test/ui/impl-trait/bound-normalization-pass.stderr +++ b/src/test/ui/impl-trait/bound-normalization-pass.stderr @@ -1,5 +1,5 @@ warning: the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash - --> $DIR/bound-normalization-pass.rs:6:12 + --> $DIR/bound-normalization-pass.rs:5:12 | LL | #![feature(impl_trait_in_bindings)] | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/impl-trait/dyn-trait-elided-two-inputs-assoc.rs b/src/test/ui/impl-trait/dyn-trait-elided-two-inputs-assoc.rs new file mode 100644 index 00000000000..3b714157384 --- /dev/null +++ b/src/test/ui/impl-trait/dyn-trait-elided-two-inputs-assoc.rs @@ -0,0 +1,16 @@ +// Test that we don't get an error with `dyn Bar` in an impl Trait +// when there are multiple inputs. The `dyn Bar` should default to `+ +// 'static`. This used to erroneously generate an error (cc #62517). +// +// check-pass + +trait Foo { type Item: ?Sized; } +trait Bar { } + +impl<T> Foo for T { + type Item = dyn Bar; +} + +fn foo(x: &str, y: &str) -> impl Foo<Item = dyn Bar> { () } + +fn main() { } diff --git a/src/test/ui/impl-trait/dyn-trait-elided-two-inputs-param.rs b/src/test/ui/impl-trait/dyn-trait-elided-two-inputs-param.rs new file mode 100644 index 00000000000..e8da52aad0e --- /dev/null +++ b/src/test/ui/impl-trait/dyn-trait-elided-two-inputs-param.rs @@ -0,0 +1,11 @@ +// Test that we don't get an error with `dyn Object` in an impl Trait +// when there are multiple inputs. The `dyn Object` should default to `+ +// 'static`. This used to erroneously generate an error (cc #62517). +// +// check-pass + +trait Alpha<Item: ?Sized> {} +trait Object {} +impl<T> Alpha<dyn Object> for T {} +fn alpha(x: &str, y: &str) -> impl Alpha<dyn Object> { () } +fn main() { } diff --git a/src/test/ui/impl-trait/dyn-trait-elided-two-inputs-ref-assoc.rs b/src/test/ui/impl-trait/dyn-trait-elided-two-inputs-ref-assoc.rs new file mode 100644 index 00000000000..aad9d89fe24 --- /dev/null +++ b/src/test/ui/impl-trait/dyn-trait-elided-two-inputs-ref-assoc.rs @@ -0,0 +1,27 @@ +// Test that we don't get an error with `dyn Bar` in an impl Trait +// when there are multiple inputs. The `dyn Bar` should default to `+ +// 'static`. This used to erroneously generate an error (cc #62517). +// +// check-pass + +trait Foo { + type Item: ?Sized; + + fn item(&self) -> Box<Self::Item> { panic!() } +} + +trait Bar { } + +impl<T> Foo for T { + type Item = dyn Bar; +} + +fn is_static<T>(_: T) where T: 'static { } + +fn bar(x: &str) -> &impl Foo<Item = dyn Bar> { &() } + +fn main() { + let s = format!("foo"); + let r = bar(&s); + is_static(r.item()); +} diff --git a/src/test/ui/impl-trait/dyn-trait-elided-two-inputs-ref-param.rs b/src/test/ui/impl-trait/dyn-trait-elided-two-inputs-ref-param.rs new file mode 100644 index 00000000000..8d34c1b6c2a --- /dev/null +++ b/src/test/ui/impl-trait/dyn-trait-elided-two-inputs-ref-param.rs @@ -0,0 +1,23 @@ +// Test that `impl Alpha<dyn Object>` resets the object-lifetime +// default to `'static`. +// +// check-pass + +trait Alpha<Item: ?Sized> { + fn item(&self) -> Box<Item> { + panic!() + } +} + +trait Object {} +impl<T> Alpha<dyn Object> for T {} +fn alpha(x: &str, y: &str) -> impl Alpha<dyn Object> { () } +fn is_static<T>(_: T) where T: 'static { } + +fn bar(x: &str) -> &impl Alpha<dyn Object> { &() } + +fn main() { + let s = format!("foo"); + let r = bar(&s); + is_static(r.item()); +} diff --git a/src/test/ui/impl-trait/issue-55872-2.rs b/src/test/ui/impl-trait/issue-55872-2.rs index dfee20ca649..1ca2e3d9065 100644 --- a/src/test/ui/impl-trait/issue-55872-2.rs +++ b/src/test/ui/impl-trait/issue-55872-2.rs @@ -1,6 +1,7 @@ // edition:2018 // ignore-tidy-linelength -#![feature(async_await, type_alias_impl_trait)] + +#![feature(type_alias_impl_trait)] pub trait Bar { type E: Copy; diff --git a/src/test/ui/impl-trait/issue-55872-2.stderr b/src/test/ui/impl-trait/issue-55872-2.stderr index 676c3fe3d4c..01371b4d5c6 100644 --- a/src/test/ui/impl-trait/issue-55872-2.stderr +++ b/src/test/ui/impl-trait/issue-55872-2.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `impl std::future::Future: std::marker::Copy` is not satisfied - --> $DIR/issue-55872-2.rs:12:5 + --> $DIR/issue-55872-2.rs:13:5 | LL | type E = impl Copy; | ^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `impl std::future::Future` @@ -7,7 +7,7 @@ LL | type E = impl Copy; = note: the return type of a function must have a statically known size error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias - --> $DIR/issue-55872-2.rs:14:28 + --> $DIR/issue-55872-2.rs:15:28 | LL | fn foo<T>() -> Self::E { | ____________________________^ diff --git a/src/test/ui/imports/local-modularized-tricky-fail-1.stderr b/src/test/ui/imports/local-modularized-tricky-fail-1.stderr index 5afdd8889ae..7d013828bd9 100644 --- a/src/test/ui/imports/local-modularized-tricky-fail-1.stderr +++ b/src/test/ui/imports/local-modularized-tricky-fail-1.stderr @@ -21,25 +21,6 @@ LL | use inner1::*; | ^^^^^^^^^ = help: consider adding an explicit import of `exported` to disambiguate -error[E0659]: `include` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) - --> $DIR/local-modularized-tricky-fail-1.rs:46:1 - | -LL | include!(); - | ^^^^^^^ ambiguous name - | - = note: `include` could refer to a macro from prelude -note: `include` could also refer to the macro defined here - --> $DIR/local-modularized-tricky-fail-1.rs:17:5 - | -LL | / macro_rules! include { -LL | | () => () -LL | | } - | |_____^ -... -LL | define_include!(); - | ------------------ in this macro invocation - = help: use `crate::include` to refer to this macro unambiguously - error[E0659]: `panic` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) --> $DIR/local-modularized-tricky-fail-1.rs:35:5 | @@ -59,6 +40,25 @@ LL | define_panic!(); | ---------------- in this macro invocation = help: use `crate::panic` to refer to this macro unambiguously +error[E0659]: `include` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) + --> $DIR/local-modularized-tricky-fail-1.rs:46:1 + | +LL | include!(); + | ^^^^^^^ ambiguous name + | + = note: `include` could refer to a macro from prelude +note: `include` could also refer to the macro defined here + --> $DIR/local-modularized-tricky-fail-1.rs:17:5 + | +LL | / macro_rules! include { +LL | | () => () +LL | | } + | |_____^ +... +LL | define_include!(); + | ------------------ in this macro invocation + = help: use `crate::include` to refer to this macro unambiguously + error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0659`. diff --git a/src/test/ui/imports/shadow_builtin_macros.stderr b/src/test/ui/imports/shadow_builtin_macros.stderr index c84226ef313..2f2ab20cdf0 100644 --- a/src/test/ui/imports/shadow_builtin_macros.stderr +++ b/src/test/ui/imports/shadow_builtin_macros.stderr @@ -14,20 +14,6 @@ LL | use foo::*; = help: or use `self::panic` to refer to this macro unambiguously error[E0659]: `panic` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) - --> $DIR/shadow_builtin_macros.rs:20:14 - | -LL | fn f() { panic!(); } - | ^^^^^ ambiguous name - | - = note: `panic` could refer to a macro from prelude -note: `panic` could also refer to the macro imported here - --> $DIR/shadow_builtin_macros.rs:19:26 - | -LL | ::two_macros::m!(use foo::panic;); - | ^^^^^^^^^^ - = help: use `self::panic` to refer to this macro unambiguously - -error[E0659]: `panic` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) --> $DIR/shadow_builtin_macros.rs:33:5 | LL | panic!(); @@ -62,6 +48,20 @@ note: `n` could also refer to the macro imported here LL | #[macro_use(n)] | ^ +error[E0659]: `panic` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) + --> $DIR/shadow_builtin_macros.rs:20:14 + | +LL | fn f() { panic!(); } + | ^^^^^ ambiguous name + | + = note: `panic` could refer to a macro from prelude +note: `panic` could also refer to the macro imported here + --> $DIR/shadow_builtin_macros.rs:19:26 + | +LL | ::two_macros::m!(use foo::panic;); + | ^^^^^^^^^^ + = help: use `self::panic` to refer to this macro unambiguously + error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0659`. diff --git a/src/test/ui/in-band-lifetimes/nested-items.rs b/src/test/ui/in-band-lifetimes/nested-items.rs new file mode 100644 index 00000000000..7de20712fba --- /dev/null +++ b/src/test/ui/in-band-lifetimes/nested-items.rs @@ -0,0 +1,20 @@ +// Test that the `'a` from the impl doesn't +// prevent us from creating a `'a` parameter +// on the `blah` function. +// +// check-pass + +#![feature(in_band_lifetimes)] + +struct Foo<'a> { + x: &'a u32 + +} + +impl Foo<'a> { + fn method(&self) { + fn blah(f: Foo<'a>) { } + } +} + +fn main() { } diff --git a/src/test/ui/include-macros/data.bin b/src/test/ui/include-macros/data.bin new file mode 100644 index 00000000000..ce4e0b8311a --- /dev/null +++ b/src/test/ui/include-macros/data.bin @@ -0,0 +1,2 @@ +This file starts with BOM. +Lines are separated by \r\n. diff --git a/src/test/ui/include-macros/normalization.rs b/src/test/ui/include-macros/normalization.rs new file mode 100644 index 00000000000..889f08e606e --- /dev/null +++ b/src/test/ui/include-macros/normalization.rs @@ -0,0 +1,12 @@ +// run-pass + +fn main() { + assert_eq!( + &include_bytes!("data.bin")[..], + &b"\xEF\xBB\xBFThis file starts with BOM.\r\nLines are separated by \\r\\n.\r\n"[..], + ); + assert_eq!( + include_str!("data.bin"), + "\u{FEFF}This file starts with BOM.\r\nLines are separated by \\r\\n.\r\n", + ); +} diff --git a/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.rs b/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.rs new file mode 100644 index 00000000000..7d75f254bfe --- /dev/null +++ b/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.rs @@ -0,0 +1,17 @@ +// edition:2018 +#![feature(impl_trait_in_bindings)] +//~^ WARN the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash + +use std::io::Error; + +fn make_unit() -> Result<(), Error> { + Ok(()) +} + +fn main() { + let fut = async { + make_unit()?; //~ ERROR type annotations needed + + Ok(()) + }; +} diff --git a/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr b/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr new file mode 100644 index 00000000000..f67e45b01d2 --- /dev/null +++ b/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr @@ -0,0 +1,19 @@ +warning: the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash + --> $DIR/cannot-infer-async-enabled-impl-trait-bindings.rs:2:12 + | +LL | #![feature(impl_trait_in_bindings)] + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +error[E0282]: type annotations needed for `impl std::future::Future` + --> $DIR/cannot-infer-async-enabled-impl-trait-bindings.rs:13:9 + | +LL | let fut = async { + | --- consider giving `fut` the explicit type `impl std::future::Future`, with the type parameters specified +LL | make_unit()?; + | ^^^^^^^^^^^^ cannot infer type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/inference/cannot-infer-async.rs b/src/test/ui/inference/cannot-infer-async.rs new file mode 100644 index 00000000000..05f62f3d8cb --- /dev/null +++ b/src/test/ui/inference/cannot-infer-async.rs @@ -0,0 +1,15 @@ +// edition:2018 + +use std::io::Error; + +fn make_unit() -> Result<(), Error> { + Ok(()) +} + +fn main() { + let fut = async { + make_unit()?; //~ ERROR type annotations needed + + Ok(()) + }; +} diff --git a/src/test/ui/inference/cannot-infer-async.stderr b/src/test/ui/inference/cannot-infer-async.stderr new file mode 100644 index 00000000000..bf31fb85cf6 --- /dev/null +++ b/src/test/ui/inference/cannot-infer-async.stderr @@ -0,0 +1,11 @@ +error[E0282]: type annotations needed + --> $DIR/cannot-infer-async.rs:11:9 + | +LL | let fut = async { + | --- consider giving `fut` a type +LL | make_unit()?; + | ^^^^^^^^^^^^ cannot infer type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/inference/cannot-infer-closure.rs b/src/test/ui/inference/cannot-infer-closure.rs new file mode 100644 index 00000000000..8f48483c254 --- /dev/null +++ b/src/test/ui/inference/cannot-infer-closure.rs @@ -0,0 +1,6 @@ +fn main() { + let x = |a: (), b: ()| { + Err(a)?; //~ ERROR type annotations needed for the closure + Ok(b) + }; +} diff --git a/src/test/ui/inference/cannot-infer-closure.stderr b/src/test/ui/inference/cannot-infer-closure.stderr new file mode 100644 index 00000000000..5f30b5d993c --- /dev/null +++ b/src/test/ui/inference/cannot-infer-closure.stderr @@ -0,0 +1,13 @@ +error[E0282]: type annotations needed for the closure `fn((), ()) -> std::result::Result<(), _>` + --> $DIR/cannot-infer-closure.rs:3:9 + | +LL | Err(a)?; + | ^^^^^^^ cannot infer type +help: give this closure an explicit return type without `_` placeholders + | +LL | let x = |a: (), b: ()| -> std::result::Result<(), _> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/issues/issue-12028.rs b/src/test/ui/issues/issue-12028.rs index d55354529a9..7c2b0d69c8b 100644 --- a/src/test/ui/issues/issue-12028.rs +++ b/src/test/ui/issues/issue-12028.rs @@ -17,8 +17,6 @@ trait StreamHasher { fn stream(&self) -> Self::S; } -////////////////////////////////////////////////////////////////////////////// - trait StreamHash<H: StreamHasher>: Hash<H> { fn input_stream(&self, stream: &mut H::S); } diff --git a/src/test/ui/issues/issue-12028.stderr b/src/test/ui/issues/issue-12028.stderr index 64694c7a8d0..24aa88c3fa3 100644 --- a/src/test/ui/issues/issue-12028.stderr +++ b/src/test/ui/issues/issue-12028.stderr @@ -1,5 +1,5 @@ error[E0284]: type annotations required: cannot resolve `<_ as StreamHasher>::S == <H as StreamHasher>::S` - --> $DIR/issue-12028.rs:29:14 + --> $DIR/issue-12028.rs:27:14 | LL | self.input_stream(&mut stream); | ^^^^^^^^^^^^ diff --git a/src/test/ui/issues/issue-13483.stderr b/src/test/ui/issues/issue-13483.stderr index 739f0612366..df9f1dd0115 100644 --- a/src/test/ui/issues/issue-13483.stderr +++ b/src/test/ui/issues/issue-13483.stderr @@ -1,10 +1,10 @@ -error: missing condition for `if` statemement +error: missing condition for `if` expression --> $DIR/issue-13483.rs:3:14 | LL | } else if { | ^ expected if condition here -error: missing condition for `if` statemement +error: missing condition for `if` expression --> $DIR/issue-13483.rs:10:14 | LL | } else if { diff --git a/src/test/ui/issues/issue-16739.rs b/src/test/ui/issues/issue-16739.rs index 54ad8fd076e..94da2ca5cab 100644 --- a/src/test/ui/issues/issue-16739.rs +++ b/src/test/ui/issues/issue-16739.rs @@ -16,8 +16,6 @@ impl FnOnce<()> for Foo { extern "rust-call" fn call_once(mut self, _: ()) -> u32 { self.call_mut(()) } } -///////////////////////////////////////////////////////////////////////// - impl FnMut<(u32,)> for Foo { extern "rust-call" fn call_mut(&mut self, (x,): (u32,)) -> u32 { self.foo + x } } @@ -27,8 +25,6 @@ impl FnOnce<(u32,)> for Foo { extern "rust-call" fn call_once(mut self, args: (u32,)) -> u32 { self.call_mut(args) } } -///////////////////////////////////////////////////////////////////////// - impl FnMut<(u32,u32)> for Foo { extern "rust-call" fn call_mut(&mut self, (x, y): (u32, u32)) -> u32 { self.foo + x + y } } diff --git a/src/test/ui/issues/issue-18159.stderr b/src/test/ui/issues/issue-18159.stderr index 6048344125c..9b890be3c78 100644 --- a/src/test/ui/issues/issue-18159.stderr +++ b/src/test/ui/issues/issue-18159.stderr @@ -2,10 +2,7 @@ error[E0282]: type annotations needed --> $DIR/issue-18159.rs:2:9 | LL | let x; - | ^ - | | - | cannot infer type - | consider giving `x` a type + | ^ consider giving `x` a type error: aborting due to previous error diff --git a/src/test/ui/issues/issue-31776.rs b/src/test/ui/issues/issue-31776.rs index c0d2c91e577..c86623ce289 100644 --- a/src/test/ui/issues/issue-31776.rs +++ b/src/test/ui/issues/issue-31776.rs @@ -13,7 +13,7 @@ mod m { } } -// ------------------------------------------------------ +// Scenario 1 pub trait Tr { type A; @@ -28,7 +28,7 @@ fn f() { } } -// ------------------------------------------------------ +// Scenario 2 trait Tr1 { type A; @@ -49,8 +49,6 @@ mod m1 { } } -// ------------------------------------------------------ - fn main() { S.s(); // Privacy error, unless `fn s` is pub let a = S2.pull().field; // Privacy error unless `field: u8` is pub diff --git a/src/test/ui/issues/issue-49074.stderr b/src/test/ui/issues/issue-49074.stderr index c557255ab50..e0d3bb3ecc2 100644 --- a/src/test/ui/issues/issue-49074.stderr +++ b/src/test/ui/issues/issue-49074.stderr @@ -1,9 +1,3 @@ -error: cannot find attribute macro `marco_use` in this scope - --> $DIR/issue-49074.rs:3:3 - | -LL | #[marco_use] // typo - | ^^^^^^^^^ help: a built-in attribute with a similar name exists: `macro_use` - error: cannot find macro `bar!` in this scope --> $DIR/issue-49074.rs:12:4 | @@ -12,5 +6,11 @@ LL | bar!(); | = help: have you added the `#[macro_use]` on the module/import? +error: cannot find attribute macro `marco_use` in this scope + --> $DIR/issue-49074.rs:3:3 + | +LL | #[marco_use] // typo + | ^^^^^^^^^ help: a built-in attribute with a similar name exists: `macro_use` + error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-50301.rs b/src/test/ui/issues/issue-50301.rs new file mode 100644 index 00000000000..47ee3e7ad70 --- /dev/null +++ b/src/test/ui/issues/issue-50301.rs @@ -0,0 +1,31 @@ +// Tests that HRTBs are correctly accepted -- https://github.com/rust-lang/rust/issues/50301 +// check-pass +trait Trait +where + for<'a> &'a Self::IntoIter: IntoIterator<Item = u32>, +{ + type IntoIter; + fn get(&self) -> Self::IntoIter; +} + +struct Impl(Vec<u32>); + +impl Trait for Impl { + type IntoIter = ImplIntoIter; + fn get(&self) -> Self::IntoIter { + ImplIntoIter(self.0.clone()) + } +} + +struct ImplIntoIter(Vec<u32>); + +impl<'a> IntoIterator for &'a ImplIntoIter { + type Item = <Self::IntoIter as Iterator>::Item; + type IntoIter = std::iter::Cloned<std::slice::Iter<'a, u32>>; + fn into_iter(self) -> Self::IntoIter { + (&self.0).into_iter().cloned() + } +} + +fn main() { +} diff --git a/src/test/ui/issues/issue-50415.rs b/src/test/ui/issues/issue-50415.rs index 20c7be772f9..151b9fe442c 100644 --- a/src/test/ui/issues/issue-50415.rs +++ b/src/test/ui/issues/issue-50415.rs @@ -1,11 +1,9 @@ // run-pass fn main() { - // -------- Simplified test case -------- - + // Simplified test case let _ = || 0..=1; - // -------- Original test case -------- - + // Original test case let full_length = 1024; let range = { // do some stuff, omit here diff --git a/src/test/ui/issues/issue-5067.rs b/src/test/ui/issues/issue-5067.rs index 616fd09907a..5857a081596 100644 --- a/src/test/ui/issues/issue-5067.rs +++ b/src/test/ui/issues/issue-5067.rs @@ -54,7 +54,7 @@ macro_rules! foo { //~^ ERROR repetition matches empty token tree } -// --- Original Issue --- // +// Original Issue macro_rules! make_vec { (a $e1:expr $($(, a $e2:expr)*)*) => ([$e1 $($(, $e2)*)*]); @@ -65,7 +65,7 @@ fn main() { let _ = make_vec![a 1, a 2, a 3]; } -// --- Minified Issue --- // +// Minified Issue macro_rules! m { ( $()* ) => {}; diff --git a/src/test/ui/iterators/iter-count-overflow-debug.rs b/src/test/ui/iterators/iter-count-overflow-debug.rs new file mode 100644 index 00000000000..d6612035750 --- /dev/null +++ b/src/test/ui/iterators/iter-count-overflow-debug.rs @@ -0,0 +1,16 @@ +// run-pass +// only-32bit too impatient for 2⁶⁴ items +// ignore-wasm32-bare compiled with panic=abort by default +// compile-flags: -C debug_assertions=yes -C opt-level=3 + +use std::panic; +use std::usize::MAX; + +fn main() { + assert_eq!((0..MAX).by_ref().count(), MAX); + + let r = panic::catch_unwind(|| { + (0..=MAX).by_ref().count() + }); + assert!(r.is_err()); +} diff --git a/src/test/ui/iterators/iter-count-overflow-ndebug.rs b/src/test/ui/iterators/iter-count-overflow-ndebug.rs new file mode 100644 index 00000000000..b755bb554f4 --- /dev/null +++ b/src/test/ui/iterators/iter-count-overflow-ndebug.rs @@ -0,0 +1,11 @@ +// run-pass +// only-32bit too impatient for 2⁶⁴ items +// compile-flags: -C debug_assertions=no -C opt-level=3 + +use std::panic; +use std::usize::MAX; + +fn main() { + assert_eq!((0..MAX).by_ref().count(), MAX); + assert_eq!((0..=MAX).by_ref().count(), 0); +} diff --git a/src/test/ui/iterators/iter-map-fold-type-length.rs b/src/test/ui/iterators/iter-map-fold-type-length.rs new file mode 100644 index 00000000000..8ce4fcd8731 --- /dev/null +++ b/src/test/ui/iterators/iter-map-fold-type-length.rs @@ -0,0 +1,38 @@ +// run-pass +//! Check that type lengths don't explode with `Map` folds. +//! +//! The normal limit is a million, and this test used to exceed 1.5 million, but +//! now we can survive an even tighter limit. Still seems excessive though... +#![type_length_limit = "256000"] + +// Custom wrapper so Iterator methods aren't specialized. +struct Iter<I>(I); + +impl<I> Iterator for Iter<I> +where + I: Iterator +{ + type Item = I::Item; + + fn next(&mut self) -> Option<Self::Item> { + self.0.next() + } +} + +fn main() { + let c = Iter(0i32..10) + .map(|x| x) + .map(|x| x) + .map(|x| x) + .map(|x| x) + .map(|x| x) + .map(|x| x) + .map(|x| x) + .map(|x| x) + .map(|x| x) + .map(|x| x) + .map(|x| x) + .map(|x| x) + .count(); + assert_eq!(c, 10); +} diff --git a/src/test/ui/iterators/iter-position-overflow-debug.rs b/src/test/ui/iterators/iter-position-overflow-debug.rs new file mode 100644 index 00000000000..f1eded31702 --- /dev/null +++ b/src/test/ui/iterators/iter-position-overflow-debug.rs @@ -0,0 +1,22 @@ +// run-pass +// only-32bit too impatient for 2⁶⁴ items +// ignore-wasm32-bare compiled with panic=abort by default +// compile-flags: -C debug_assertions=yes -C opt-level=3 + +use std::panic; +use std::usize::MAX; + +fn main() { + let n = MAX as u64; + assert_eq!((0..).by_ref().position(|i| i >= n), Some(MAX)); + + let r = panic::catch_unwind(|| { + (0..).by_ref().position(|i| i > n) + }); + assert!(r.is_err()); + + let r = panic::catch_unwind(|| { + (0..=n + 1).by_ref().position(|_| false) + }); + assert!(r.is_err()); +} diff --git a/src/test/ui/iterators/iter-position-overflow-ndebug.rs b/src/test/ui/iterators/iter-position-overflow-ndebug.rs new file mode 100644 index 00000000000..368f9c0c02b --- /dev/null +++ b/src/test/ui/iterators/iter-position-overflow-ndebug.rs @@ -0,0 +1,13 @@ +// run-pass +// only-32bit too impatient for 2⁶⁴ items +// compile-flags: -C debug_assertions=no -C opt-level=3 + +use std::panic; +use std::usize::MAX; + +fn main() { + let n = MAX as u64; + assert_eq!((0..).by_ref().position(|i| i >= n), Some(MAX)); + assert_eq!((0..).by_ref().position(|i| i > n), Some(0)); + assert_eq!((0..=n + 1).by_ref().position(|_| false), None); +} diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs index 2370084b072..ea0d0ccbc55 100644 --- a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs +++ b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs @@ -6,7 +6,7 @@ trait Future { use std::error::Error; fn foo() -> impl Future<Item=(), Error=Box<dyn Error>> { -//~^ ERROR missing lifetime +//~^ ERROR not satisfied Ok(()) } diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr index 06b317ce952..228582d0001 100644 --- a/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr +++ b/src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr @@ -1,11 +1,11 @@ -error[E0106]: missing lifetime specifier - --> $DIR/lifetime-elision-return-type-trait.rs:8:44 +error[E0277]: the trait bound `std::result::Result<(), _>: Future` is not satisfied + --> $DIR/lifetime-elision-return-type-trait.rs:8:13 | LL | fn foo() -> impl Future<Item=(), Error=Box<dyn Error>> { - | ^^^^^^^^^ help: consider giving it a 'static lifetime: `dyn Error + 'static` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Future` is not implemented for `std::result::Result<(), _>` | - = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from + = note: the return type of a function must have a statically known size error: aborting due to previous error -For more information about this error, try `rustc --explain E0106`. +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/lint/lint-qualification.rs b/src/test/ui/lint/lint-qualification.rs index 1b24191a111..0cace0ca035 100644 --- a/src/test/ui/lint/lint-qualification.rs +++ b/src/test/ui/lint/lint-qualification.rs @@ -1,5 +1,5 @@ #![deny(unused_qualifications)] -#[allow(deprecated)] +#![allow(deprecated)] mod foo { pub fn bar() {} diff --git a/src/test/ui/lint/lint-unused-mut-variables.rs b/src/test/ui/lint/lint-unused-mut-variables.rs index 2957f931110..f140546b048 100644 --- a/src/test/ui/lint/lint-unused-mut-variables.rs +++ b/src/test/ui/lint/lint-unused-mut-variables.rs @@ -3,7 +3,7 @@ // Exercise the unused_mut attribute in some positive and negative cases #![deny(unused_mut)] -#![feature(async_await, async_closure, param_attrs)] +#![feature(async_closure, param_attrs)] async fn baz_async( mut a: i32, diff --git a/src/test/ui/lint/lint-unused-variables.rs b/src/test/ui/lint/lint-unused-variables.rs index a1660d23511..06b818636f9 100644 --- a/src/test/ui/lint/lint-unused-variables.rs +++ b/src/test/ui/lint/lint-unused-variables.rs @@ -1,7 +1,7 @@ // compile-flags: --cfg something // edition:2018 -#![feature(async_await, async_closure, param_attrs)] +#![feature(async_closure, param_attrs)] #![deny(unused_variables)] async fn foo_async( diff --git a/src/test/ui/lint/uninitialized-zeroed.rs b/src/test/ui/lint/uninitialized-zeroed.rs index d816479bbbb..5cf62b86912 100644 --- a/src/test/ui/lint/uninitialized-zeroed.rs +++ b/src/test/ui/lint/uninitialized-zeroed.rs @@ -2,11 +2,13 @@ // This test checks that calling `mem::{uninitialized,zeroed}` with certain types results // in a lint. -#![feature(never_type)] +#![feature(never_type, rustc_attrs)] #![allow(deprecated)] #![deny(invalid_value)] use std::mem::{self, MaybeUninit}; +use std::ptr::NonNull; +use std::num::NonZeroU32; enum Void {} @@ -16,6 +18,11 @@ struct RefPair((&'static i32, i32)); struct Wrap<T> { wrapped: T } enum WrapEnum<T> { Wrapped(T) } +#[rustc_layout_scalar_valid_range_start(0)] +#[rustc_layout_scalar_valid_range_end(128)] +#[repr(transparent)] +pub(crate) struct NonBig(u64); + #[allow(unused)] fn generic<T: 'static>() { unsafe { @@ -29,6 +36,7 @@ fn generic<T: 'static>() { fn main() { unsafe { + // Things that cannot even be zero. let _val: ! = mem::zeroed(); //~ ERROR: does not permit zero-initialization let _val: ! = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized @@ -56,11 +64,28 @@ fn main() { let _val: Wrap<(RefPair, i32)> = mem::zeroed(); //~ ERROR: does not permit zero-initialization let _val: Wrap<(RefPair, i32)> = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized - // Some types that should work just fine. + let _val: NonNull<i32> = mem::zeroed(); //~ ERROR: does not permit zero-initialization + let _val: NonNull<i32> = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + // Things that can be zero, but not uninit. + let _val: bool = mem::zeroed(); + let _val: bool = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: Wrap<char> = mem::zeroed(); + let _val: Wrap<char> = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + let _val: NonBig = mem::zeroed(); + let _val: NonBig = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized + + // Transmute-from-0 + let _val: &'static i32 = mem::transmute(0usize); //~ ERROR: does not permit zero-initialization + let _val: &'static [i32] = mem::transmute((0usize, 0usize)); //~ ERROR: does not permit zero-initialization + let _val: NonZeroU32 = mem::transmute(0); //~ ERROR: does not permit zero-initialization + + // Some more types that should work just fine. let _val: Option<&'static i32> = mem::zeroed(); let _val: Option<fn()> = mem::zeroed(); let _val: MaybeUninit<&'static i32> = mem::zeroed(); - let _val: bool = mem::zeroed(); let _val: i32 = mem::zeroed(); } } diff --git a/src/test/ui/lint/uninitialized-zeroed.stderr b/src/test/ui/lint/uninitialized-zeroed.stderr index 1b15fc21525..a36a32a39a1 100644 --- a/src/test/ui/lint/uninitialized-zeroed.stderr +++ b/src/test/ui/lint/uninitialized-zeroed.stderr @@ -1,5 +1,5 @@ error: the type `&'static T` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:22:32 + --> $DIR/uninitialized-zeroed.rs:29:32 | LL | let _val: &'static T = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -15,7 +15,7 @@ LL | #![deny(invalid_value)] = note: References must be non-null error: the type `&'static T` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:23:32 + --> $DIR/uninitialized-zeroed.rs:30:32 | LL | let _val: &'static T = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -26,7 +26,7 @@ LL | let _val: &'static T = mem::uninitialized(); = note: References must be non-null error: the type `Wrap<&'static T>` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:25:38 + --> $DIR/uninitialized-zeroed.rs:32:38 | LL | let _val: Wrap<&'static T> = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -35,13 +35,13 @@ LL | let _val: Wrap<&'static T> = mem::zeroed(); | help: use `MaybeUninit<T>` instead | note: References must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:16:18 + --> $DIR/uninitialized-zeroed.rs:18:18 | LL | struct Wrap<T> { wrapped: T } | ^^^^^^^^^^ error: the type `Wrap<&'static T>` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:26:38 + --> $DIR/uninitialized-zeroed.rs:33:38 | LL | let _val: Wrap<&'static T> = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -50,13 +50,13 @@ LL | let _val: Wrap<&'static T> = mem::uninitialized(); | help: use `MaybeUninit<T>` instead | note: References must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:16:18 + --> $DIR/uninitialized-zeroed.rs:18:18 | LL | struct Wrap<T> { wrapped: T } | ^^^^^^^^^^ error: the type `!` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:32:23 + --> $DIR/uninitialized-zeroed.rs:40:23 | LL | let _val: ! = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -67,7 +67,7 @@ LL | let _val: ! = mem::zeroed(); = note: The never type (`!`) has no valid value error: the type `!` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:33:23 + --> $DIR/uninitialized-zeroed.rs:41:23 | LL | let _val: ! = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -78,7 +78,7 @@ LL | let _val: ! = mem::uninitialized(); = note: The never type (`!`) has no valid value error: the type `(i32, !)` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:35:30 + --> $DIR/uninitialized-zeroed.rs:43:30 | LL | let _val: (i32, !) = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -89,7 +89,7 @@ LL | let _val: (i32, !) = mem::zeroed(); = note: The never type (`!`) has no valid value error: the type `(i32, !)` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:36:30 + --> $DIR/uninitialized-zeroed.rs:44:30 | LL | let _val: (i32, !) = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -100,7 +100,7 @@ LL | let _val: (i32, !) = mem::uninitialized(); = note: The never type (`!`) has no valid value error: the type `Void` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:38:26 + --> $DIR/uninitialized-zeroed.rs:46:26 | LL | let _val: Void = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -111,7 +111,7 @@ LL | let _val: Void = mem::zeroed(); = note: 0-variant enums have no valid value error: the type `Void` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:39:26 + --> $DIR/uninitialized-zeroed.rs:47:26 | LL | let _val: Void = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -122,7 +122,7 @@ LL | let _val: Void = mem::uninitialized(); = note: 0-variant enums have no valid value error: the type `&'static i32` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:41:34 + --> $DIR/uninitialized-zeroed.rs:49:34 | LL | let _val: &'static i32 = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -133,7 +133,7 @@ LL | let _val: &'static i32 = mem::zeroed(); = note: References must be non-null error: the type `&'static i32` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:42:34 + --> $DIR/uninitialized-zeroed.rs:50:34 | LL | let _val: &'static i32 = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -144,7 +144,7 @@ LL | let _val: &'static i32 = mem::uninitialized(); = note: References must be non-null error: the type `Ref` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:44:25 + --> $DIR/uninitialized-zeroed.rs:52:25 | LL | let _val: Ref = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -153,13 +153,13 @@ LL | let _val: Ref = mem::zeroed(); | help: use `MaybeUninit<T>` instead | note: References must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:13:12 + --> $DIR/uninitialized-zeroed.rs:15:12 | LL | struct Ref(&'static i32); | ^^^^^^^^^^^^ error: the type `Ref` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:45:25 + --> $DIR/uninitialized-zeroed.rs:53:25 | LL | let _val: Ref = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -168,13 +168,13 @@ LL | let _val: Ref = mem::uninitialized(); | help: use `MaybeUninit<T>` instead | note: References must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:13:12 + --> $DIR/uninitialized-zeroed.rs:15:12 | LL | struct Ref(&'static i32); | ^^^^^^^^^^^^ error: the type `fn()` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:47:26 + --> $DIR/uninitialized-zeroed.rs:55:26 | LL | let _val: fn() = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -185,7 +185,7 @@ LL | let _val: fn() = mem::zeroed(); = note: Function pointers must be non-null error: the type `fn()` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:48:26 + --> $DIR/uninitialized-zeroed.rs:56:26 | LL | let _val: fn() = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -196,7 +196,7 @@ LL | let _val: fn() = mem::uninitialized(); = note: Function pointers must be non-null error: the type `Wrap<fn()>` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:50:32 + --> $DIR/uninitialized-zeroed.rs:58:32 | LL | let _val: Wrap<fn()> = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -205,13 +205,13 @@ LL | let _val: Wrap<fn()> = mem::zeroed(); | help: use `MaybeUninit<T>` instead | note: Function pointers must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:16:18 + --> $DIR/uninitialized-zeroed.rs:18:18 | LL | struct Wrap<T> { wrapped: T } | ^^^^^^^^^^ error: the type `Wrap<fn()>` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:51:32 + --> $DIR/uninitialized-zeroed.rs:59:32 | LL | let _val: Wrap<fn()> = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -220,13 +220,13 @@ LL | let _val: Wrap<fn()> = mem::uninitialized(); | help: use `MaybeUninit<T>` instead | note: Function pointers must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:16:18 + --> $DIR/uninitialized-zeroed.rs:18:18 | LL | struct Wrap<T> { wrapped: T } | ^^^^^^^^^^ error: the type `WrapEnum<fn()>` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:53:36 + --> $DIR/uninitialized-zeroed.rs:61:36 | LL | let _val: WrapEnum<fn()> = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -235,13 +235,13 @@ LL | let _val: WrapEnum<fn()> = mem::zeroed(); | help: use `MaybeUninit<T>` instead | note: Function pointers must be non-null (in this enum field) - --> $DIR/uninitialized-zeroed.rs:17:28 + --> $DIR/uninitialized-zeroed.rs:19:28 | LL | enum WrapEnum<T> { Wrapped(T) } | ^ error: the type `WrapEnum<fn()>` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:54:36 + --> $DIR/uninitialized-zeroed.rs:62:36 | LL | let _val: WrapEnum<fn()> = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -250,13 +250,13 @@ LL | let _val: WrapEnum<fn()> = mem::uninitialized(); | help: use `MaybeUninit<T>` instead | note: Function pointers must be non-null (in this enum field) - --> $DIR/uninitialized-zeroed.rs:17:28 + --> $DIR/uninitialized-zeroed.rs:19:28 | LL | enum WrapEnum<T> { Wrapped(T) } | ^ error: the type `Wrap<(RefPair, i32)>` does not permit zero-initialization - --> $DIR/uninitialized-zeroed.rs:56:42 + --> $DIR/uninitialized-zeroed.rs:64:42 | LL | let _val: Wrap<(RefPair, i32)> = mem::zeroed(); | ^^^^^^^^^^^^^ @@ -265,13 +265,13 @@ LL | let _val: Wrap<(RefPair, i32)> = mem::zeroed(); | help: use `MaybeUninit<T>` instead | note: References must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:14:16 + --> $DIR/uninitialized-zeroed.rs:16:16 | LL | struct RefPair((&'static i32, i32)); | ^^^^^^^^^^^^^^^^^^^ error: the type `Wrap<(RefPair, i32)>` does not permit being left uninitialized - --> $DIR/uninitialized-zeroed.rs:57:42 + --> $DIR/uninitialized-zeroed.rs:65:42 | LL | let _val: Wrap<(RefPair, i32)> = mem::uninitialized(); | ^^^^^^^^^^^^^^^^^^^^ @@ -280,10 +280,102 @@ LL | let _val: Wrap<(RefPair, i32)> = mem::uninitialized(); | help: use `MaybeUninit<T>` instead | note: References must be non-null (in this struct field) - --> $DIR/uninitialized-zeroed.rs:14:16 + --> $DIR/uninitialized-zeroed.rs:16:16 | LL | struct RefPair((&'static i32, i32)); | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to 22 previous errors +error: the type `std::ptr::NonNull<i32>` does not permit zero-initialization + --> $DIR/uninitialized-zeroed.rs:67:34 + | +LL | let _val: NonNull<i32> = mem::zeroed(); + | ^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead + | + = note: std::ptr::NonNull<i32> must be non-null + +error: the type `std::ptr::NonNull<i32>` does not permit being left uninitialized + --> $DIR/uninitialized-zeroed.rs:68:34 + | +LL | let _val: NonNull<i32> = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead + | + = note: std::ptr::NonNull<i32> must be non-null + +error: the type `bool` does not permit being left uninitialized + --> $DIR/uninitialized-zeroed.rs:72:26 + | +LL | let _val: bool = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead + | + = note: Booleans must be `true` or `false` + +error: the type `Wrap<char>` does not permit being left uninitialized + --> $DIR/uninitialized-zeroed.rs:75:32 + | +LL | let _val: Wrap<char> = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead + | +note: Characters must be a valid unicode codepoint (in this struct field) + --> $DIR/uninitialized-zeroed.rs:18:18 + | +LL | struct Wrap<T> { wrapped: T } + | ^^^^^^^^^^ + +error: the type `NonBig` does not permit being left uninitialized + --> $DIR/uninitialized-zeroed.rs:78:28 + | +LL | let _val: NonBig = mem::uninitialized(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead + | + = note: NonBig must be initialized inside its custom valid range + +error: the type `&'static i32` does not permit zero-initialization + --> $DIR/uninitialized-zeroed.rs:81:34 + | +LL | let _val: &'static i32 = mem::transmute(0usize); + | ^^^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead + | + = note: References must be non-null + +error: the type `&'static [i32]` does not permit zero-initialization + --> $DIR/uninitialized-zeroed.rs:82:36 + | +LL | let _val: &'static [i32] = mem::transmute((0usize, 0usize)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead + | + = note: References must be non-null + +error: the type `std::num::NonZeroU32` does not permit zero-initialization + --> $DIR/uninitialized-zeroed.rs:83:32 + | +LL | let _val: NonZeroU32 = mem::transmute(0); + | ^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit<T>` instead + | + = note: std::num::NonZeroU32 must be non-null + +error: aborting due to 30 previous errors diff --git a/src/test/ui/macros/restricted-shadowing-modern.rs b/src/test/ui/macros/restricted-shadowing-modern.rs index a8818507d75..1151a829eba 100644 --- a/src/test/ui/macros/restricted-shadowing-modern.rs +++ b/src/test/ui/macros/restricted-shadowing-modern.rs @@ -95,8 +95,6 @@ macro include() { m!() } - // ----------------------------------------------------------- - fn check1() { macro m() {} { diff --git a/src/test/ui/macros/restricted-shadowing-modern.stderr b/src/test/ui/macros/restricted-shadowing-modern.stderr index d147debeb51..12075d42b9a 100644 --- a/src/test/ui/macros/restricted-shadowing-modern.stderr +++ b/src/test/ui/macros/restricted-shadowing-modern.stderr @@ -1,5 +1,5 @@ error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) - --> $DIR/restricted-shadowing-modern.rs:106:17 + --> $DIR/restricted-shadowing-modern.rs:104:17 | LL | m!(); | ^ ambiguous name @@ -16,7 +16,7 @@ LL | macro m() { Right } LL | include!(); | ----------- in this macro invocation note: `m` could also refer to the macro defined here - --> $DIR/restricted-shadowing-modern.rs:101:9 + --> $DIR/restricted-shadowing-modern.rs:99:9 | LL | macro m() {} | ^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | include!(); | ----------- in this macro invocation error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) - --> $DIR/restricted-shadowing-modern.rs:149:33 + --> $DIR/restricted-shadowing-modern.rs:147:33 | LL | macro gen_invoc() { m!() } | ^ ambiguous name @@ -42,7 +42,7 @@ LL | macro m() { Right } LL | include!(); | ----------- in this macro invocation note: `m` could also refer to the macro defined here - --> $DIR/restricted-shadowing-modern.rs:145:9 + --> $DIR/restricted-shadowing-modern.rs:143:9 | LL | macro m() {} | ^^^^^^^^^^^^ @@ -51,7 +51,7 @@ LL | include!(); | ----------- in this macro invocation error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) - --> $DIR/restricted-shadowing-modern.rs:158:13 + --> $DIR/restricted-shadowing-modern.rs:156:13 | LL | m!(); | ^ ambiguous name @@ -68,7 +68,7 @@ LL | macro m() { Right } LL | include!(); | ----------- in this macro invocation note: `m` could also refer to the macro defined here - --> $DIR/restricted-shadowing-modern.rs:155:9 + --> $DIR/restricted-shadowing-modern.rs:153:9 | LL | macro m() {} | ^^^^^^^^^^^^ @@ -77,7 +77,7 @@ LL | include!(); | ----------- in this macro invocation error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) - --> $DIR/restricted-shadowing-modern.rs:174:13 + --> $DIR/restricted-shadowing-modern.rs:172:13 | LL | m!(); | ^ ambiguous name @@ -103,7 +103,7 @@ LL | include!(); | ----------- in this macro invocation error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) - --> $DIR/restricted-shadowing-modern.rs:192:17 + --> $DIR/restricted-shadowing-modern.rs:190:17 | LL | m!(); | ^ ambiguous name @@ -129,7 +129,7 @@ LL | include!(); | ----------- in this macro invocation error[E0659]: `m` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution) - --> $DIR/restricted-shadowing-modern.rs:235:33 + --> $DIR/restricted-shadowing-modern.rs:233:33 | LL | macro gen_invoc() { m!() } | ^ ambiguous name diff --git a/src/test/ui/macros/same-sequence-span.stderr b/src/test/ui/macros/same-sequence-span.stderr index aee1b4c9c5d..250773a1853 100644 --- a/src/test/ui/macros/same-sequence-span.stderr +++ b/src/test/ui/macros/same-sequence-span.stderr @@ -18,7 +18,10 @@ error: `$x:expr` may be followed by `$y:tt`, which is not allowed for `expr` fra --> $DIR/same-sequence-span.rs:20:1 | LL | proc_macro_sequence::make_foo!(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not allowed after `expr` fragments + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | not allowed after `expr` fragments + | in this macro invocation | = note: allowed there are: `=>`, `,` or `;` @@ -26,7 +29,10 @@ error: `$x:expr` may be followed by `=`, which is not allowed for `expr` fragmen --> $DIR/same-sequence-span.rs:20:1 | LL | proc_macro_sequence::make_foo!(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not allowed after `expr` fragments + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | not allowed after `expr` fragments + | in this macro invocation | = note: allowed there are: `=>`, `,` or `;` diff --git a/src/test/ui/macros/trace-macro.stderr b/src/test/ui/macros/trace-macro.stderr index 287f7b297d5..202a9235adb 100644 --- a/src/test/ui/macros/trace-macro.stderr +++ b/src/test/ui/macros/trace-macro.stderr @@ -5,5 +5,5 @@ LL | println!("Hello, World!"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: expanding `println! { "Hello, World!" }` - = note: to `{ $crate :: io :: _print (format_args_nl ! ("Hello, World!")) ; }` + = note: to `{ $crate :: io :: _print ($crate :: format_args_nl ! ("Hello, World!")) ; }` diff --git a/src/test/ui/match/match-unresolved-one-arm.stderr b/src/test/ui/match/match-unresolved-one-arm.stderr index ad8569b4802..77df9921b75 100644 --- a/src/test/ui/match/match-unresolved-one-arm.stderr +++ b/src/test/ui/match/match-unresolved-one-arm.stderr @@ -2,10 +2,7 @@ error[E0282]: type annotations needed --> $DIR/match-unresolved-one-arm.rs:4:9 | LL | let x = match () { - | ^ - | | - | cannot infer type - | consider giving `x` a type + | ^ consider giving `x` a type error: aborting due to previous error diff --git a/src/test/ui/methods/method-projection.rs b/src/test/ui/methods/method-projection.rs index cf33d53968b..21d983f192a 100644 --- a/src/test/ui/methods/method-projection.rs +++ b/src/test/ui/methods/method-projection.rs @@ -2,9 +2,6 @@ // Test that we can use method notation to call methods based on a // projection bound from a trait. Issue #20469. -/////////////////////////////////////////////////////////////////////////// - - trait MakeString { fn make_string(&self) -> String; } @@ -21,8 +18,6 @@ impl MakeString for usize { } } -/////////////////////////////////////////////////////////////////////////// - trait Foo { type F: MakeString; @@ -33,8 +28,6 @@ fn foo<F:Foo>(f: &F) -> String { f.get().make_string() } -/////////////////////////////////////////////////////////////////////////// - struct SomeStruct { field: isize, } @@ -47,8 +40,6 @@ impl Foo for SomeStruct { } } -/////////////////////////////////////////////////////////////////////////// - struct SomeOtherStruct { field: usize, } diff --git a/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.rs b/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.rs new file mode 100644 index 00000000000..7337383e297 --- /dev/null +++ b/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.rs @@ -0,0 +1,27 @@ +// Test that `dyn Bar<Item = XX>` uses `'static` as the default object +// lifetime bound for the type `XX`. + +trait Foo<'a> { + type Item: ?Sized; + + fn item(&self) -> Box<Self::Item> { panic!() } +} + +trait Bar { } + +impl<T> Foo<'_> for T { + type Item = dyn Bar; +} + +fn is_static<T>(_: T) where T: 'static { } + +// Here, we should default to `dyn Bar + 'static`, but the current +// code forces us into a conservative, hacky path. +fn bar<'a>(x: &'a str) -> &'a dyn Foo<'a, Item = dyn Bar> { &() } +//~^ ERROR please supply an explicit bound + +fn main() { + let s = format!("foo"); + let r = bar(&s); + is_static(r.item()); +} diff --git a/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.stderr b/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.stderr new file mode 100644 index 00000000000..9dbf7a78ed7 --- /dev/null +++ b/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.stderr @@ -0,0 +1,8 @@ +error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound + --> $DIR/object-lifetime-default-dyn-binding-nonstatic1.rs:20:50 + | +LL | fn bar<'a>(x: &'a str) -> &'a dyn Foo<'a, Item = dyn Bar> { &() } + | ^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.rs b/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.rs new file mode 100644 index 00000000000..2a7415174f8 --- /dev/null +++ b/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.rs @@ -0,0 +1,30 @@ +// Test that `dyn Bar<Item = XX>` uses `'static` as the default object +// lifetime bound for the type `XX`. + +trait Foo<'a> { + type Item: 'a + ?Sized; + + fn item(&self) -> Box<Self::Item> { panic!() } +} + +trait Bar { } + +impl<T> Foo<'_> for T { + type Item = dyn Bar; +} + +fn is_static<T>(_: T) where T: 'static { } + +// Here, we default to `dyn Bar + 'a`. Or, we *should*, but the +// current code forces us into a conservative, hacky path. +fn bar<'a>(x: &'a str) -> &'a dyn Foo<'a, Item = dyn Bar> { &() } +//~^ ERROR please supply an explicit bound + +fn main() { + let s = format!("foo"); + let r = bar(&s); + + // If it weren't for the conservative path above, we'd expect an + // error here. + is_static(r.item()); +} diff --git a/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.stderr b/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.stderr new file mode 100644 index 00000000000..d069f52ce47 --- /dev/null +++ b/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.stderr @@ -0,0 +1,8 @@ +error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound + --> $DIR/object-lifetime-default-dyn-binding-nonstatic2.rs:20:50 + | +LL | fn bar<'a>(x: &'a str) -> &'a dyn Foo<'a, Item = dyn Bar> { &() } + | ^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.rs b/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.rs new file mode 100644 index 00000000000..51be999a632 --- /dev/null +++ b/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.rs @@ -0,0 +1,23 @@ +// Test that `dyn Bar<Item = XX>` uses `'static` as the default object +// lifetime bound for the type `XX`. + +trait Foo<'a> { + type Item: ?Sized; + + fn item(&self) -> Box<Self::Item> { panic!() } +} + +trait Bar { } + +fn is_static<T>(_: T) where T: 'static { } + +// Here, we should default to `dyn Bar + 'static`, but the current +// code forces us into a conservative, hacky path. +fn bar(x: &str) -> &dyn Foo<Item = dyn Bar> { &() } +//~^ ERROR please supply an explicit bound + +fn main() { + let s = format!("foo"); + let r = bar(&s); + is_static(r.item()); +} diff --git a/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.stderr b/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.stderr new file mode 100644 index 00000000000..9c7b6b98f2e --- /dev/null +++ b/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.stderr @@ -0,0 +1,8 @@ +error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound + --> $DIR/object-lifetime-default-dyn-binding-nonstatic3.rs:16:36 + | +LL | fn bar(x: &str) -> &dyn Foo<Item = dyn Bar> { &() } + | ^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-static.rs b/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-static.rs new file mode 100644 index 00000000000..339f3356bd7 --- /dev/null +++ b/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-static.rs @@ -0,0 +1,28 @@ +// Test that `dyn Bar<Item = XX>` uses `'static` as the default object +// lifetime bound for the type `XX`. +// +// check-pass + +trait Foo { + type Item: ?Sized; + + fn item(&self) -> Box<Self::Item> { panic!() } +} + +trait Bar { } + +impl<T> Foo for T { + type Item = dyn Bar; +} + +fn is_static<T>(_: T) where T: 'static { } + +// Here, we default to `dyn Bar + 'static`, and not `&'x dyn Foo<Item +// = dyn Bar + 'x>`. +fn bar(x: &str) -> &dyn Foo<Item = dyn Bar> { &() } + +fn main() { + let s = format!("foo"); + let r = bar(&s); + is_static(r.item()); +} diff --git a/src/test/ui/obsolete-in-place/bad.rs b/src/test/ui/obsolete-in-place/bad.rs index 3530862f767..a491bb21a57 100644 --- a/src/test/ui/obsolete-in-place/bad.rs +++ b/src/test/ui/obsolete-in-place/bad.rs @@ -2,7 +2,7 @@ fn foo() { let (x, y) = (0, 0); - x <- y; //~ ERROR expected one of + x <- y; //~ ERROR unexpected token: `<-` } fn main() { diff --git a/src/test/ui/obsolete-in-place/bad.stderr b/src/test/ui/obsolete-in-place/bad.stderr index 373b7ea4218..8a731b6240b 100644 --- a/src/test/ui/obsolete-in-place/bad.stderr +++ b/src/test/ui/obsolete-in-place/bad.stderr @@ -1,8 +1,12 @@ -error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `<-` +error: unexpected token: `<-` --> $DIR/bad.rs:5:7 | LL | x <- y; - | ^^ expected one of 8 possible tokens here + | ^^ +help: if you meant to write a comparison against a negative value, add a space in between `<` and `-` + | +LL | x < - y; + | ^^^ error: expected expression, found keyword `in` --> $DIR/bad.rs:10:5 diff --git a/src/test/ui/parser/doc-before-semi.rs b/src/test/ui/parser/doc-before-semi.rs index 405a7e1e2a3..c3f478fe420 100644 --- a/src/test/ui/parser/doc-before-semi.rs +++ b/src/test/ui/parser/doc-before-semi.rs @@ -3,4 +3,6 @@ fn main() { //~^ ERROR found a documentation comment that doesn't document anything //~| HELP maybe a comment was intended ; + //~^ WARNING unnecessary trailing semicolon + //~| HELP remove this semicolon } diff --git a/src/test/ui/parser/doc-before-semi.stderr b/src/test/ui/parser/doc-before-semi.stderr index e6bade18d0a..b9ac30b09b2 100644 --- a/src/test/ui/parser/doc-before-semi.stderr +++ b/src/test/ui/parser/doc-before-semi.stderr @@ -6,6 +6,14 @@ LL | /// hi | = help: doc comments must come before what they document, maybe a comment was intended with `//`? +warning: unnecessary trailing semicolon + --> $DIR/doc-before-semi.rs:5:5 + | +LL | ; + | ^ help: remove this semicolon + | + = note: `#[warn(redundant_semicolon)]` on by default + error: aborting due to previous error For more information about this error, try `rustc --explain E0585`. diff --git a/src/test/ui/parser/pat-lt-bracket-6.rs b/src/test/ui/parser/pat-lt-bracket-6.rs index 7b972183099..f27caa5d78c 100644 --- a/src/test/ui/parser/pat-lt-bracket-6.rs +++ b/src/test/ui/parser/pat-lt-bracket-6.rs @@ -2,8 +2,9 @@ fn main() { struct Test(&'static u8, [u8; 0]); let x = Test(&0, []); - let Test(&desc[..]) = x; //~ ERROR: expected one of `)`, `,`, or `@`, found `[` - //~^ ERROR subslice patterns are unstable + let Test(&desc[..]) = x; + //~^ ERROR: expected one of `)`, `,`, `@`, or `|`, found `[` + //~^^ ERROR subslice patterns are unstable } const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types diff --git a/src/test/ui/parser/pat-lt-bracket-6.stderr b/src/test/ui/parser/pat-lt-bracket-6.stderr index 201465b2c85..6f08f0a9d95 100644 --- a/src/test/ui/parser/pat-lt-bracket-6.stderr +++ b/src/test/ui/parser/pat-lt-bracket-6.stderr @@ -1,8 +1,8 @@ -error: expected one of `)`, `,`, or `@`, found `[` +error: expected one of `)`, `,`, `@`, or `|`, found `[` --> $DIR/pat-lt-bracket-6.rs:5:19 | LL | let Test(&desc[..]) = x; - | ^ expected one of `)`, `,`, or `@` here + | ^ expected one of `)`, `,`, `@`, or `|` here error[E0658]: subslice patterns are unstable --> $DIR/pat-lt-bracket-6.rs:5:20 @@ -14,7 +14,7 @@ LL | let Test(&desc[..]) = x; = help: add `#![feature(slice_patterns)]` to the crate attributes to enable error[E0308]: mismatched types - --> $DIR/pat-lt-bracket-6.rs:9:30 + --> $DIR/pat-lt-bracket-6.rs:10:30 | LL | const RECOVERY_WITNESS: () = 0; | ^ expected (), found integer diff --git a/src/test/ui/parser/pat-lt-bracket-7.rs b/src/test/ui/parser/pat-lt-bracket-7.rs index 020fdb845e8..327aef5ad15 100644 --- a/src/test/ui/parser/pat-lt-bracket-7.rs +++ b/src/test/ui/parser/pat-lt-bracket-7.rs @@ -2,7 +2,8 @@ fn main() { struct Thing(u8, [u8; 0]); let foo = core::iter::empty(); - for Thing(x[]) in foo {} //~ ERROR: expected one of `)`, `,`, or `@`, found `[` + for Thing(x[]) in foo {} + //~^ ERROR: expected one of `)`, `,`, `@`, or `|`, found `[` } const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types diff --git a/src/test/ui/parser/pat-lt-bracket-7.stderr b/src/test/ui/parser/pat-lt-bracket-7.stderr index 17557efa49e..196f1c0ae91 100644 --- a/src/test/ui/parser/pat-lt-bracket-7.stderr +++ b/src/test/ui/parser/pat-lt-bracket-7.stderr @@ -1,11 +1,11 @@ -error: expected one of `)`, `,`, or `@`, found `[` +error: expected one of `)`, `,`, `@`, or `|`, found `[` --> $DIR/pat-lt-bracket-7.rs:5:16 | LL | for Thing(x[]) in foo {} - | ^ expected one of `)`, `,`, or `@` here + | ^ expected one of `)`, `,`, `@`, or `|` here error[E0308]: mismatched types - --> $DIR/pat-lt-bracket-7.rs:8:30 + --> $DIR/pat-lt-bracket-7.rs:9:30 | LL | const RECOVERY_WITNESS: () = 0; | ^ expected (), found integer diff --git a/src/test/ui/parser/recover-for-loop-parens-around-head.rs b/src/test/ui/parser/recover-for-loop-parens-around-head.rs index e6c59fcf22d..c6be2c90667 100644 --- a/src/test/ui/parser/recover-for-loop-parens-around-head.rs +++ b/src/test/ui/parser/recover-for-loop-parens-around-head.rs @@ -8,7 +8,7 @@ fn main() { let vec = vec![1, 2, 3]; for ( elem in vec ) { - //~^ ERROR expected one of `)`, `,`, or `@`, found `in` + //~^ ERROR expected one of `)`, `,`, `@`, or `|`, found `in` //~| ERROR unexpected closing `)` const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types } diff --git a/src/test/ui/parser/recover-for-loop-parens-around-head.stderr b/src/test/ui/parser/recover-for-loop-parens-around-head.stderr index c160e646c28..1b5b6cca092 100644 --- a/src/test/ui/parser/recover-for-loop-parens-around-head.stderr +++ b/src/test/ui/parser/recover-for-loop-parens-around-head.stderr @@ -1,8 +1,8 @@ -error: expected one of `)`, `,`, or `@`, found `in` +error: expected one of `)`, `,`, `@`, or `|`, found `in` --> $DIR/recover-for-loop-parens-around-head.rs:10:16 | LL | for ( elem in vec ) { - | ^^ expected one of `)`, `,`, or `@` here + | ^^ expected one of `)`, `,`, `@`, or `|` here error: unexpected closing `)` --> $DIR/recover-for-loop-parens-around-head.rs:10:23 diff --git a/src/test/ui/placement-syntax.rs b/src/test/ui/placement-syntax.rs index 2edd78ec8ab..4df96dedbd4 100644 --- a/src/test/ui/placement-syntax.rs +++ b/src/test/ui/placement-syntax.rs @@ -1,6 +1,6 @@ fn main() { let x = -5; - if x<-1 { //~ ERROR expected `{`, found `<-` + if x<-1 { //~ ERROR unexpected token: `<-` println!("ok"); } } diff --git a/src/test/ui/placement-syntax.stderr b/src/test/ui/placement-syntax.stderr index e90acce168e..e26931e60d8 100644 --- a/src/test/ui/placement-syntax.stderr +++ b/src/test/ui/placement-syntax.stderr @@ -1,10 +1,12 @@ -error: expected `{`, found `<-` +error: unexpected token: `<-` --> $DIR/placement-syntax.rs:3:9 | LL | if x<-1 { - | -- ^^ expected `{` - | | - | this `if` statement has a condition, but no block + | ^^ +help: if you meant to write a comparison against a negative value, add a space in between `<` and `-` + | +LL | if x< -1 { + | ^^^ error: aborting due to previous error diff --git a/src/test/ui/proc-macro/auxiliary/gen-macro-rules.rs b/src/test/ui/proc-macro/auxiliary/gen-macro-rules.rs new file mode 100644 index 00000000000..d4b67d6b0b0 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/gen-macro-rules.rs @@ -0,0 +1,12 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro_derive(repro)] +pub fn proc_macro_hack_expr(_input: TokenStream) -> TokenStream { + "macro_rules! m {()=>{}}".parse().unwrap() +} diff --git a/src/test/ui/proc-macro/gen-macro-rules.rs b/src/test/ui/proc-macro/gen-macro-rules.rs new file mode 100644 index 00000000000..13ad27f9372 --- /dev/null +++ b/src/test/ui/proc-macro/gen-macro-rules.rs @@ -0,0 +1,13 @@ +// Derive macros can generate `macro_rules` items, regression test for issue #63651. + +// check-pass +// aux-build:gen-macro-rules.rs + +extern crate gen_macro_rules as repro; + +#[derive(repro::repro)] +pub struct S; + +m!(); // OK + +fn main() {} diff --git a/src/test/ui/proc-macro/generate-mod.stderr b/src/test/ui/proc-macro/generate-mod.stderr index 51bbb23da75..829d8bf4c81 100644 --- a/src/test/ui/proc-macro/generate-mod.stderr +++ b/src/test/ui/proc-macro/generate-mod.stderr @@ -2,13 +2,19 @@ error[E0412]: cannot find type `FromOutside` in this scope --> $DIR/generate-mod.rs:9:1 | LL | generate_mod::check!(); - | ^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope + | ^^^^^^^^^^^^^^^^^^^^^^^ + | | + | not found in this scope + | in this macro invocation error[E0412]: cannot find type `Outer` in this scope --> $DIR/generate-mod.rs:9:1 | LL | generate_mod::check!(); - | ^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope + | ^^^^^^^^^^^^^^^^^^^^^^^ + | | + | not found in this scope + | in this macro invocation error[E0412]: cannot find type `FromOutside` in this scope --> $DIR/generate-mod.rs:12:1 diff --git a/src/test/ui/proc-macro/invalid-punct-ident-4.stderr b/src/test/ui/proc-macro/invalid-punct-ident-4.stderr index da2bf07a1a3..65e40172ef5 100644 --- a/src/test/ui/proc-macro/invalid-punct-ident-4.stderr +++ b/src/test/ui/proc-macro/invalid-punct-ident-4.stderr @@ -2,7 +2,10 @@ error: unexpected close delimiter: `)` --> $DIR/invalid-punct-ident-4.rs:6:1 | LL | lexer_failure!(); - | ^^^^^^^^^^^^^^^^^ unexpected close delimiter + | ^^^^^^^^^^^^^^^^^ + | | + | unexpected close delimiter + | in this macro invocation error: proc macro panicked --> $DIR/invalid-punct-ident-4.rs:6:1 diff --git a/src/test/ui/proc-macro/lints_in_proc_macros.stderr b/src/test/ui/proc-macro/lints_in_proc_macros.stderr index 2d97cd700be..f28b8c9fb73 100644 --- a/src/test/ui/proc-macro/lints_in_proc_macros.stderr +++ b/src/test/ui/proc-macro/lints_in_proc_macros.stderr @@ -2,7 +2,10 @@ error[E0425]: cannot find value `foobar2` in this scope --> $DIR/lints_in_proc_macros.rs:12:5 | LL | bang_proc_macro2!(); - | ^^^^^^^^^^^^^^^^^^^^ help: a local variable with a similar name exists: `foobar` + | ^^^^^^^^^^^^^^^^^^^^ + | | + | help: a local variable with a similar name exists: `foobar` + | in this macro invocation error: aborting due to previous error diff --git a/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr b/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr index b2f12478828..0c863e91967 100644 --- a/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr +++ b/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr @@ -88,18 +88,6 @@ error: expected derive macro, found macro `crate::my_macro` LL | #[derive(crate::my_macro)] | ^^^^^^^^^^^^^^^ not a derive macro -error: cannot find attribute macro `my_macro` in this scope - --> $DIR/macro-namespace-reserved-2.rs:38:3 - | -LL | #[my_macro] - | ^^^^^^^^ - -error: cannot find derive macro `my_macro` in this scope - --> $DIR/macro-namespace-reserved-2.rs:48:10 - | -LL | #[derive(my_macro)] - | ^^^^^^^^ - error: cannot find macro `my_macro_attr!` in this scope --> $DIR/macro-namespace-reserved-2.rs:28:5 | @@ -112,5 +100,17 @@ error: cannot find macro `MyTrait!` in this scope LL | MyTrait!(); | ^^^^^^^ +error: cannot find attribute macro `my_macro` in this scope + --> $DIR/macro-namespace-reserved-2.rs:38:3 + | +LL | #[my_macro] + | ^^^^^^^^ + +error: cannot find derive macro `my_macro` in this scope + --> $DIR/macro-namespace-reserved-2.rs:48:10 + | +LL | #[derive(my_macro)] + | ^^^^^^^^ + error: aborting due to 19 previous errors diff --git a/src/test/ui/proc-macro/multispan.stderr b/src/test/ui/proc-macro/multispan.stderr index 44af07a7942..a0c1f9cd5c0 100644 --- a/src/test/ui/proc-macro/multispan.stderr +++ b/src/test/ui/proc-macro/multispan.stderr @@ -2,7 +2,7 @@ error: hello to you, too! --> $DIR/multispan.rs:14:5 | LL | hello!(hi); - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ in this macro invocation | note: found these 'hi's --> $DIR/multispan.rs:14:12 @@ -14,7 +14,7 @@ error: hello to you, too! --> $DIR/multispan.rs:17:5 | LL | hello!(hi hi); - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ in this macro invocation | note: found these 'hi's --> $DIR/multispan.rs:17:12 @@ -26,7 +26,7 @@ error: hello to you, too! --> $DIR/multispan.rs:20:5 | LL | hello!(hi hi hi); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ in this macro invocation | note: found these 'hi's --> $DIR/multispan.rs:20:12 @@ -38,7 +38,7 @@ error: hello to you, too! --> $DIR/multispan.rs:23:5 | LL | hello!(hi hey hi yo hi beep beep hi hi); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in this macro invocation | note: found these 'hi's --> $DIR/multispan.rs:23:12 @@ -50,7 +50,7 @@ error: hello to you, too! --> $DIR/multispan.rs:24:5 | LL | hello!(hi there, hi how are you? hi... hi.); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in this macro invocation | note: found these 'hi's --> $DIR/multispan.rs:24:12 @@ -62,7 +62,7 @@ error: hello to you, too! --> $DIR/multispan.rs:25:5 | LL | hello!(whoah. hi di hi di ho); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in this macro invocation | note: found these 'hi's --> $DIR/multispan.rs:25:19 @@ -74,7 +74,7 @@ error: hello to you, too! --> $DIR/multispan.rs:26:5 | LL | hello!(hi good hi and good bye); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in this macro invocation | note: found these 'hi's --> $DIR/multispan.rs:26:12 diff --git a/src/test/ui/proc-macro/span-preservation.rs b/src/test/ui/proc-macro/span-preservation.rs index 0a82d28e9e5..55835cb88f4 100644 --- a/src/test/ui/proc-macro/span-preservation.rs +++ b/src/test/ui/proc-macro/span-preservation.rs @@ -9,7 +9,7 @@ extern crate test_macros; #[recollect_attr] fn a() { - let x: usize = "hello";;;;; //~ ERROR mismatched types + let x: usize = "hello"; //~ ERROR mismatched types } #[recollect_attr] diff --git a/src/test/ui/proc-macro/span-preservation.stderr b/src/test/ui/proc-macro/span-preservation.stderr index cf03deee7e4..0290f4b2cc9 100644 --- a/src/test/ui/proc-macro/span-preservation.stderr +++ b/src/test/ui/proc-macro/span-preservation.stderr @@ -6,7 +6,7 @@ error[E0308]: mismatched types error[E0308]: mismatched types --> $DIR/span-preservation.rs:12:20 | -LL | let x: usize = "hello";;;;; +LL | let x: usize = "hello"; | ^^^^^^^ expected usize, found reference | = note: expected type `usize` diff --git a/src/test/ui/proc-macro/subspan.stderr b/src/test/ui/proc-macro/subspan.stderr index 5117dd6d32d..06715c197bc 100644 --- a/src/test/ui/proc-macro/subspan.stderr +++ b/src/test/ui/proc-macro/subspan.stderr @@ -2,7 +2,7 @@ error: found 'hi's --> $DIR/subspan.rs:11:1 | LL | subspan!("hi"); - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ in this macro invocation | note: here --> $DIR/subspan.rs:11:11 @@ -14,7 +14,7 @@ error: found 'hi's --> $DIR/subspan.rs:14:1 | LL | subspan!("hihi"); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ in this macro invocation | note: here --> $DIR/subspan.rs:14:11 @@ -26,7 +26,7 @@ error: found 'hi's --> $DIR/subspan.rs:17:1 | LL | subspan!("hihihi"); - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ in this macro invocation | note: here --> $DIR/subspan.rs:17:11 @@ -38,7 +38,7 @@ error: found 'hi's --> $DIR/subspan.rs:20:1 | LL | subspan!("why I hide? hi!"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in this macro invocation | note: here --> $DIR/subspan.rs:20:17 @@ -50,7 +50,7 @@ error: found 'hi's --> $DIR/subspan.rs:21:1 | LL | subspan!("hey, hi, hidy, hidy, hi hi"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in this macro invocation | note: here --> $DIR/subspan.rs:21:16 @@ -62,7 +62,7 @@ error: found 'hi's --> $DIR/subspan.rs:22:1 | LL | subspan!("this is a hi, and this is another hi"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in this macro invocation | note: here --> $DIR/subspan.rs:22:12 @@ -74,7 +74,7 @@ error: found 'hi's --> $DIR/subspan.rs:23:1 | LL | subspan!("how are you this evening"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in this macro invocation | note: here --> $DIR/subspan.rs:23:24 @@ -86,7 +86,7 @@ error: found 'hi's --> $DIR/subspan.rs:24:1 | LL | subspan!("this is highly eradic"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ in this macro invocation | note: here --> $DIR/subspan.rs:24:12 diff --git a/src/test/ui/proc-macro/three-equals.stderr b/src/test/ui/proc-macro/three-equals.stderr index f8dfa841d4f..0a6cbe13098 100644 --- a/src/test/ui/proc-macro/three-equals.stderr +++ b/src/test/ui/proc-macro/three-equals.stderr @@ -2,7 +2,7 @@ error: found 2 equal signs, need exactly 3 --> $DIR/three-equals.rs:15:5 | LL | three_equals!(==); - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ in this macro invocation | = help: input must be: `===` diff --git a/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.migrate.nll.stderr b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.migrate.nll.stderr index 867eafe2529..4944f2649b7 100644 --- a/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.migrate.nll.stderr +++ b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.migrate.nll.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:43:12 + --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:39:12 | LL | fn with_assoc<'a,'b>() { | -- -- lifetime `'b` defined here diff --git a/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.migrate.stderr b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.migrate.stderr index f31f25bf00b..61be0778c99 100644 --- a/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.migrate.stderr +++ b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.migrate.stderr @@ -1,16 +1,16 @@ error[E0491]: in type `&'a WithAssoc<TheType<'b>>`, reference has a longer lifetime than the data it references - --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:43:12 + --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:39:12 | LL | let _: &'a WithAssoc<TheType<'b>> = loop { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime 'a as defined on the function body at 37:15 - --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:37:15 +note: the pointer is valid for the lifetime 'a as defined on the function body at 33:15 + --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:33:15 | LL | fn with_assoc<'a,'b>() { | ^^ -note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 37:18 - --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:37:18 +note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 33:18 + --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:33:18 | LL | fn with_assoc<'a,'b>() { | ^^ diff --git a/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.nll.stderr b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.nll.stderr index 867eafe2529..4944f2649b7 100644 --- a/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.nll.stderr +++ b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.nll.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:43:12 + --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:39:12 | LL | fn with_assoc<'a,'b>() { | -- -- lifetime `'b` defined here diff --git a/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.rs b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.rs index 97c55593600..046d010002e 100644 --- a/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.rs +++ b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.rs @@ -8,8 +8,6 @@ #![allow(dead_code)] -/////////////////////////////////////////////////////////////////////////// - pub trait TheTrait { type TheAssocType; } @@ -28,8 +26,6 @@ impl<'b> TheTrait for TheType<'b> { impl<'b> TheSubTrait for TheType<'b> { } -/////////////////////////////////////////////////////////////////////////// - pub struct WithAssoc<T:TheSubTrait> { m: [T; 0] } diff --git a/src/test/ui/regions/regions-outlives-projection-container-hrtb.migrate.nll.stderr b/src/test/ui/regions/regions-outlives-projection-container-hrtb.migrate.nll.stderr index 5028663ba6d..eed9934be12 100644 --- a/src/test/ui/regions/regions-outlives-projection-container-hrtb.migrate.nll.stderr +++ b/src/test/ui/regions/regions-outlives-projection-container-hrtb.migrate.nll.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/regions-outlives-projection-container-hrtb.rs:35:12 + --> $DIR/regions-outlives-projection-container-hrtb.rs:30:12 | LL | fn with_assoc<'a,'b>() { | -- -- lifetime `'b` defined here @@ -10,7 +10,7 @@ LL | let _: &'a WithHrAssoc<TheType<'b>> = loop { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a` error: lifetime may not live long enough - --> $DIR/regions-outlives-projection-container-hrtb.rs:57:12 + --> $DIR/regions-outlives-projection-container-hrtb.rs:50:12 | LL | fn with_assoc_sub<'a,'b>() { | -- -- lifetime `'b` defined here diff --git a/src/test/ui/regions/regions-outlives-projection-container-hrtb.migrate.stderr b/src/test/ui/regions/regions-outlives-projection-container-hrtb.migrate.stderr index d8330184008..ed5800940ee 100644 --- a/src/test/ui/regions/regions-outlives-projection-container-hrtb.migrate.stderr +++ b/src/test/ui/regions/regions-outlives-projection-container-hrtb.migrate.stderr @@ -1,33 +1,33 @@ error[E0491]: in type `&'a WithHrAssoc<TheType<'b>>`, reference has a longer lifetime than the data it references - --> $DIR/regions-outlives-projection-container-hrtb.rs:35:12 + --> $DIR/regions-outlives-projection-container-hrtb.rs:30:12 | LL | let _: &'a WithHrAssoc<TheType<'b>> = loop { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime 'a as defined on the function body at 32:15 - --> $DIR/regions-outlives-projection-container-hrtb.rs:32:15 +note: the pointer is valid for the lifetime 'a as defined on the function body at 27:15 + --> $DIR/regions-outlives-projection-container-hrtb.rs:27:15 | LL | fn with_assoc<'a,'b>() { | ^^ -note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 32:18 - --> $DIR/regions-outlives-projection-container-hrtb.rs:32:18 +note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 27:18 + --> $DIR/regions-outlives-projection-container-hrtb.rs:27:18 | LL | fn with_assoc<'a,'b>() { | ^^ error[E0491]: in type `&'a WithHrAssocSub<TheType<'b>>`, reference has a longer lifetime than the data it references - --> $DIR/regions-outlives-projection-container-hrtb.rs:57:12 + --> $DIR/regions-outlives-projection-container-hrtb.rs:50:12 | LL | let _: &'a WithHrAssocSub<TheType<'b>> = loop { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime 'a as defined on the function body at 53:19 - --> $DIR/regions-outlives-projection-container-hrtb.rs:53:19 +note: the pointer is valid for the lifetime 'a as defined on the function body at 46:19 + --> $DIR/regions-outlives-projection-container-hrtb.rs:46:19 | LL | fn with_assoc_sub<'a,'b>() { | ^^ -note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 53:22 - --> $DIR/regions-outlives-projection-container-hrtb.rs:53:22 +note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 46:22 + --> $DIR/regions-outlives-projection-container-hrtb.rs:46:22 | LL | fn with_assoc_sub<'a,'b>() { | ^^ diff --git a/src/test/ui/regions/regions-outlives-projection-container-hrtb.nll.stderr b/src/test/ui/regions/regions-outlives-projection-container-hrtb.nll.stderr index 5028663ba6d..eed9934be12 100644 --- a/src/test/ui/regions/regions-outlives-projection-container-hrtb.nll.stderr +++ b/src/test/ui/regions/regions-outlives-projection-container-hrtb.nll.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/regions-outlives-projection-container-hrtb.rs:35:12 + --> $DIR/regions-outlives-projection-container-hrtb.rs:30:12 | LL | fn with_assoc<'a,'b>() { | -- -- lifetime `'b` defined here @@ -10,7 +10,7 @@ LL | let _: &'a WithHrAssoc<TheType<'b>> = loop { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a` error: lifetime may not live long enough - --> $DIR/regions-outlives-projection-container-hrtb.rs:57:12 + --> $DIR/regions-outlives-projection-container-hrtb.rs:50:12 | LL | fn with_assoc_sub<'a,'b>() { | -- -- lifetime `'b` defined here diff --git a/src/test/ui/regions/regions-outlives-projection-container-hrtb.rs b/src/test/ui/regions/regions-outlives-projection-container-hrtb.rs index 407a4fdf59b..cee741184ca 100644 --- a/src/test/ui/regions/regions-outlives-projection-container-hrtb.rs +++ b/src/test/ui/regions/regions-outlives-projection-container-hrtb.rs @@ -6,9 +6,6 @@ #![allow(dead_code)] - -/////////////////////////////////////////////////////////////////////////// - pub trait TheTrait<'b> { type TheAssocType; } @@ -21,8 +18,6 @@ impl<'a,'b> TheTrait<'a> for TheType<'b> { type TheAssocType = &'b (); } -/////////////////////////////////////////////////////////////////////////// - pub struct WithHrAssoc<T> where for<'a> T : TheTrait<'a> { @@ -37,8 +32,6 @@ fn with_assoc<'a,'b>() { //[nll]~^^ ERROR lifetime may not live long enough } -/////////////////////////////////////////////////////////////////////////// - pub trait TheSubTrait : for<'a> TheTrait<'a> { } diff --git a/src/test/ui/regions/regions-outlives-projection-container-wc.migrate.nll.stderr b/src/test/ui/regions/regions-outlives-projection-container-wc.migrate.nll.stderr index 880fe17b740..8c54d8da0a0 100644 --- a/src/test/ui/regions/regions-outlives-projection-container-wc.migrate.nll.stderr +++ b/src/test/ui/regions/regions-outlives-projection-container-wc.migrate.nll.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/regions-outlives-projection-container-wc.rs:37:12 + --> $DIR/regions-outlives-projection-container-wc.rs:33:12 | LL | fn with_assoc<'a,'b>() { | -- -- lifetime `'b` defined here diff --git a/src/test/ui/regions/regions-outlives-projection-container-wc.migrate.stderr b/src/test/ui/regions/regions-outlives-projection-container-wc.migrate.stderr index 9e31065ca4e..152e6c5600c 100644 --- a/src/test/ui/regions/regions-outlives-projection-container-wc.migrate.stderr +++ b/src/test/ui/regions/regions-outlives-projection-container-wc.migrate.stderr @@ -1,16 +1,16 @@ error[E0491]: in type `&'a WithAssoc<TheType<'b>>`, reference has a longer lifetime than the data it references - --> $DIR/regions-outlives-projection-container-wc.rs:37:12 + --> $DIR/regions-outlives-projection-container-wc.rs:33:12 | LL | let _: &'a WithAssoc<TheType<'b>> = loop { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime 'a as defined on the function body at 31:15 - --> $DIR/regions-outlives-projection-container-wc.rs:31:15 +note: the pointer is valid for the lifetime 'a as defined on the function body at 27:15 + --> $DIR/regions-outlives-projection-container-wc.rs:27:15 | LL | fn with_assoc<'a,'b>() { | ^^ -note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 31:18 - --> $DIR/regions-outlives-projection-container-wc.rs:31:18 +note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 27:18 + --> $DIR/regions-outlives-projection-container-wc.rs:27:18 | LL | fn with_assoc<'a,'b>() { | ^^ diff --git a/src/test/ui/regions/regions-outlives-projection-container-wc.nll.stderr b/src/test/ui/regions/regions-outlives-projection-container-wc.nll.stderr index 880fe17b740..8c54d8da0a0 100644 --- a/src/test/ui/regions/regions-outlives-projection-container-wc.nll.stderr +++ b/src/test/ui/regions/regions-outlives-projection-container-wc.nll.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/regions-outlives-projection-container-wc.rs:37:12 + --> $DIR/regions-outlives-projection-container-wc.rs:33:12 | LL | fn with_assoc<'a,'b>() { | -- -- lifetime `'b` defined here diff --git a/src/test/ui/regions/regions-outlives-projection-container-wc.rs b/src/test/ui/regions/regions-outlives-projection-container-wc.rs index 5037ea536da..99965f33390 100644 --- a/src/test/ui/regions/regions-outlives-projection-container-wc.rs +++ b/src/test/ui/regions/regions-outlives-projection-container-wc.rs @@ -8,8 +8,6 @@ #![allow(dead_code)] -/////////////////////////////////////////////////////////////////////////// - pub trait TheTrait { type TheAssocType; } @@ -22,8 +20,6 @@ impl<'b> TheTrait for TheType<'b> { type TheAssocType = &'b (); } -/////////////////////////////////////////////////////////////////////////// - pub struct WithAssoc<T> where T : TheTrait { m: [T; 0] } diff --git a/src/test/ui/regions/regions-outlives-projection-container.nll.stderr b/src/test/ui/regions/regions-outlives-projection-container.nll.stderr index ef87d02ec08..2cf6e245d19 100644 --- a/src/test/ui/regions/regions-outlives-projection-container.nll.stderr +++ b/src/test/ui/regions/regions-outlives-projection-container.nll.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/regions-outlives-projection-container.rs:40:13 + --> $DIR/regions-outlives-projection-container.rs:36:13 | LL | fn with_assoc<'a,'b>() { | -- -- lifetime `'b` defined here @@ -10,7 +10,7 @@ LL | let _x: &'a WithAssoc<TheType<'b>> = loop { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a` error: lifetime may not live long enough - --> $DIR/regions-outlives-projection-container.rs:58:13 + --> $DIR/regions-outlives-projection-container.rs:54:13 | LL | fn without_assoc<'a,'b>() { | -- -- lifetime `'b` defined here @@ -21,7 +21,7 @@ LL | let _x: &'a WithoutAssoc<TheType<'b>> = loop { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'b` must outlive `'a` error: lifetime may not live long enough - --> $DIR/regions-outlives-projection-container.rs:67:5 + --> $DIR/regions-outlives-projection-container.rs:63:5 | LL | fn call_with_assoc<'a,'b>() { | -- -- lifetime `'b` defined here @@ -32,7 +32,7 @@ LL | call::<&'a WithAssoc<TheType<'b>>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a` error: lifetime may not live long enough - --> $DIR/regions-outlives-projection-container.rs:74:5 + --> $DIR/regions-outlives-projection-container.rs:70:5 | LL | fn call_without_assoc<'a,'b>() { | -- -- lifetime `'b` defined here diff --git a/src/test/ui/regions/regions-outlives-projection-container.rs b/src/test/ui/regions/regions-outlives-projection-container.rs index 78305c06939..3afc600becb 100644 --- a/src/test/ui/regions/regions-outlives-projection-container.rs +++ b/src/test/ui/regions/regions-outlives-projection-container.rs @@ -5,8 +5,6 @@ #![allow(dead_code)] #![feature(rustc_attrs)] -/////////////////////////////////////////////////////////////////////////// - pub trait TheTrait { type TheAssocType; } @@ -19,8 +17,6 @@ impl<'b> TheTrait for TheType<'b> { type TheAssocType = &'b (); } -/////////////////////////////////////////////////////////////////////////// - pub struct WithAssoc<T:TheTrait> { m: [T; 0] } diff --git a/src/test/ui/regions/regions-outlives-projection-container.stderr b/src/test/ui/regions/regions-outlives-projection-container.stderr index b50347ac964..3c1a98a3c01 100644 --- a/src/test/ui/regions/regions-outlives-projection-container.stderr +++ b/src/test/ui/regions/regions-outlives-projection-container.stderr @@ -1,67 +1,67 @@ error[E0491]: in type `&'a WithAssoc<TheType<'b>>`, reference has a longer lifetime than the data it references - --> $DIR/regions-outlives-projection-container.rs:40:13 + --> $DIR/regions-outlives-projection-container.rs:36:13 | LL | let _x: &'a WithAssoc<TheType<'b>> = loop { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime 'a as defined on the function body at 32:15 - --> $DIR/regions-outlives-projection-container.rs:32:15 +note: the pointer is valid for the lifetime 'a as defined on the function body at 28:15 + --> $DIR/regions-outlives-projection-container.rs:28:15 | LL | fn with_assoc<'a,'b>() { | ^^ -note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 32:18 - --> $DIR/regions-outlives-projection-container.rs:32:18 +note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 28:18 + --> $DIR/regions-outlives-projection-container.rs:28:18 | LL | fn with_assoc<'a,'b>() { | ^^ error[E0491]: in type `&'a WithoutAssoc<TheType<'b>>`, reference has a longer lifetime than the data it references - --> $DIR/regions-outlives-projection-container.rs:58:13 + --> $DIR/regions-outlives-projection-container.rs:54:13 | LL | let _x: &'a WithoutAssoc<TheType<'b>> = loop { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime 'a as defined on the function body at 54:18 - --> $DIR/regions-outlives-projection-container.rs:54:18 +note: the pointer is valid for the lifetime 'a as defined on the function body at 50:18 + --> $DIR/regions-outlives-projection-container.rs:50:18 | LL | fn without_assoc<'a,'b>() { | ^^ -note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 54:21 - --> $DIR/regions-outlives-projection-container.rs:54:21 +note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 50:21 + --> $DIR/regions-outlives-projection-container.rs:50:21 | LL | fn without_assoc<'a,'b>() { | ^^ error[E0491]: in type `&'a WithAssoc<TheType<'b>>`, reference has a longer lifetime than the data it references - --> $DIR/regions-outlives-projection-container.rs:67:12 + --> $DIR/regions-outlives-projection-container.rs:63:12 | LL | call::<&'a WithAssoc<TheType<'b>>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime 'a as defined on the function body at 62:20 - --> $DIR/regions-outlives-projection-container.rs:62:20 +note: the pointer is valid for the lifetime 'a as defined on the function body at 58:20 + --> $DIR/regions-outlives-projection-container.rs:58:20 | LL | fn call_with_assoc<'a,'b>() { | ^^ -note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 62:23 - --> $DIR/regions-outlives-projection-container.rs:62:23 +note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 58:23 + --> $DIR/regions-outlives-projection-container.rs:58:23 | LL | fn call_with_assoc<'a,'b>() { | ^^ error[E0491]: in type `&'a WithoutAssoc<TheType<'b>>`, reference has a longer lifetime than the data it references - --> $DIR/regions-outlives-projection-container.rs:74:12 + --> $DIR/regions-outlives-projection-container.rs:70:12 | LL | call::<&'a WithoutAssoc<TheType<'b>>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime 'a as defined on the function body at 71:23 - --> $DIR/regions-outlives-projection-container.rs:71:23 +note: the pointer is valid for the lifetime 'a as defined on the function body at 67:23 + --> $DIR/regions-outlives-projection-container.rs:67:23 | LL | fn call_without_assoc<'a,'b>() { | ^^ -note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 71:26 - --> $DIR/regions-outlives-projection-container.rs:71:26 +note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 67:26 + --> $DIR/regions-outlives-projection-container.rs:67:26 | LL | fn call_without_assoc<'a,'b>() { | ^^ diff --git a/src/test/ui/reserved/reserved-attr-on-macro.stderr b/src/test/ui/reserved/reserved-attr-on-macro.stderr index d4b97d290ea..856162b318d 100644 --- a/src/test/ui/reserved/reserved-attr-on-macro.stderr +++ b/src/test/ui/reserved/reserved-attr-on-macro.stderr @@ -7,12 +7,6 @@ LL | #[rustc_attribute_should_be_reserved] = note: for more information, see https://github.com/rust-lang/rust/issues/29642 = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable -error: cannot find attribute macro `rustc_attribute_should_be_reserved` in this scope - --> $DIR/reserved-attr-on-macro.rs:1:3 - | -LL | #[rustc_attribute_should_be_reserved] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error: cannot determine resolution for the macro `foo` --> $DIR/reserved-attr-on-macro.rs:10:5 | @@ -21,6 +15,12 @@ LL | foo!(); | = note: import resolution is stuck, try simplifying macro imports +error: cannot find attribute macro `rustc_attribute_should_be_reserved` in this scope + --> $DIR/reserved-attr-on-macro.rs:1:3 + | +LL | #[rustc_attribute_should_be_reserved] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.rs b/src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.rs index 069332ffa25..5ad6e23cf2a 100644 --- a/src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.rs +++ b/src/test/ui/rfc-2565-param-attrs/param-attrs-cfg.rs @@ -1,7 +1,7 @@ // compile-flags: --cfg something // edition:2018 -#![feature(async_await, async_closure, param_attrs)] +#![feature(async_closure, param_attrs)] #![deny(unused_variables)] extern "C" { diff --git a/src/test/ui/rfc1598-generic-associated-types/shadowing.rs b/src/test/ui/rfc1598-generic-associated-types/shadowing.rs index 03492631cb7..f5197fd01bf 100644 --- a/src/test/ui/rfc1598-generic-associated-types/shadowing.rs +++ b/src/test/ui/rfc1598-generic-associated-types/shadowing.rs @@ -1,12 +1,9 @@ +#![allow(incomplete_features)] #![feature(generic_associated_types)] -//FIXME(#44265): The lifetime shadowing and type parameter shadowing -// should cause an error. Now it compiles (erroneously) and this will be addressed -// by a future PR. Then remove the following: -// build-pass (FIXME(62277): could be check-pass?) - trait Shadow<'a> { - type Bar<'a>; // Error: shadowed lifetime + //FIXME(#44265): The lifetime parameter shadowing should cause an error. + type Bar<'a>; } trait NoShadow<'a> { @@ -14,11 +11,12 @@ trait NoShadow<'a> { } impl<'a> NoShadow<'a> for &'a u32 { - type Bar<'a> = i32; // Error: shadowed lifetime + //FIXME(#44265): The lifetime parameter shadowing should cause an error. + type Bar<'a> = i32; } trait ShadowT<T> { - type Bar<T>; // Error: shadowed type parameter + type Bar<T>; //~ ERROR the name `T` is already used } trait NoShadowT<T> { @@ -26,7 +24,7 @@ trait NoShadowT<T> { } impl<T> NoShadowT<T> for Option<T> { - type Bar<T> = i32; // Error: shadowed type parameter + type Bar<T> = i32; //~ ERROR the name `T` is already used } fn main() {} diff --git a/src/test/ui/rfc1598-generic-associated-types/shadowing.stderr b/src/test/ui/rfc1598-generic-associated-types/shadowing.stderr index 9526df258c4..a06c6350845 100644 --- a/src/test/ui/rfc1598-generic-associated-types/shadowing.stderr +++ b/src/test/ui/rfc1598-generic-associated-types/shadowing.stderr @@ -1,8 +1,19 @@ -warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash - --> $DIR/shadowing.rs:1:12 +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters + --> $DIR/shadowing.rs:19:14 | -LL | #![feature(generic_associated_types)] - | ^^^^^^^^^^^^^^^^^^^^^^^^ +LL | trait ShadowT<T> { + | - first use of `T` +LL | type Bar<T>; + | ^ already used + +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters + --> $DIR/shadowing.rs:27:14 | - = note: `#[warn(incomplete_features)]` on by default +LL | impl<T> NoShadowT<T> for Option<T> { + | - first use of `T` +LL | type Bar<T> = i32; + | ^ already used + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0403`. diff --git a/src/test/ui/rust-unstable-column-gated.rs b/src/test/ui/rust-unstable-column-gated.rs deleted file mode 100644 index 053806ead2d..00000000000 --- a/src/test/ui/rust-unstable-column-gated.rs +++ /dev/null @@ -1,4 +0,0 @@ -fn main() { - println!("{}", __rust_unstable_column!()); - //~^ ERROR use of unstable library feature '__rust_unstable_column' -} diff --git a/src/test/ui/rust-unstable-column-gated.stderr b/src/test/ui/rust-unstable-column-gated.stderr deleted file mode 100644 index 7db1b01fb0e..00000000000 --- a/src/test/ui/rust-unstable-column-gated.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0658]: use of unstable library feature '__rust_unstable_column': internal implementation detail of the `panic` macro - --> $DIR/rust-unstable-column-gated.rs:2:20 - | -LL | println!("{}", __rust_unstable_column!()); - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(__rust_unstable_column)]` to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime-async.rs b/src/test/ui/self/arbitrary_self_types_pin_lifetime-async.rs new file mode 100644 index 00000000000..f3474bc1f9f --- /dev/null +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime-async.rs @@ -0,0 +1,35 @@ +// check-pass +// edition:2018 + +use std::pin::Pin; +use std::task::{Context, Poll}; + +struct Foo; + +impl Foo { + async fn pin_ref(self: Pin<&Self>) -> Pin<&Self> { self } + + async fn pin_mut(self: Pin<&mut Self>) -> Pin<&mut Self> { self } + + async fn pin_pin_pin_ref(self: Pin<Pin<Pin<&Self>>>) -> Pin<Pin<Pin<&Self>>> { self } + + async fn pin_ref_impl_trait(self: Pin<&Self>) -> impl Clone + '_ { self } + + fn b(self: Pin<&Foo>, f: &Foo) -> Pin<&Foo> { self } +} + +type Alias<T> = Pin<T>; +impl Foo { + async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> Alias<&Self> { self } +} + +// FIXME(Centril): extend with the rest of the non-`async fn` test +// when we allow `async fn`s inside traits and trait implementations. + +fn main() { + let mut foo = Foo; + { Pin::new(&foo).pin_ref() }; + { Pin::new(&mut foo).pin_mut() }; + { Pin::new(Pin::new(Pin::new(&foo))).pin_pin_pin_ref() }; + { Pin::new(&foo).pin_ref_impl_trait() }; +} diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.nll.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.nll.stderr new file mode 100644 index 00000000000..a585b4fdbe6 --- /dev/null +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.nll.stderr @@ -0,0 +1,14 @@ +error: lifetime may not live long enough + --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:48 + | +LL | async fn f(self: Pin<&Self>) -> impl Clone { self } + | - ^^^^^^^^ returning this value requires that `'_` must outlive `'static` + | | + | lifetime `'_` defined here +help: to allow this `impl Trait` to capture borrowed data with lifetime `'_`, add `'_` as a constraint + | +LL | async fn f(self: Pin<&Self>) -> impl Clone + '_ { self } + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.rs b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.rs new file mode 100644 index 00000000000..0afe631f1e3 --- /dev/null +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.rs @@ -0,0 +1,14 @@ +// edition:2018 + +use std::pin::Pin; + +struct Foo; + +impl Foo { + async fn f(self: Pin<&Self>) -> impl Clone { self } + //~^ ERROR cannot infer an appropriate lifetime +} + +fn main() { + { Pin::new(&Foo).f() }; +} diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr new file mode 100644 index 00000000000..2fb152475a1 --- /dev/null +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr @@ -0,0 +1,20 @@ +error: cannot infer an appropriate lifetime + --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:16 + | +LL | async fn f(self: Pin<&Self>) -> impl Clone { self } + | ^^^^ ---------- this return type evaluates to the `'static` lifetime... + | | + | ...but this borrow... + | +note: ...can't outlive the lifetime '_ as defined on the method body at 8:26 + --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:26 + | +LL | async fn f(self: Pin<&Self>) -> impl Clone { self } + | ^ +help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime '_ as defined on the method body at 8:26 + | +LL | async fn f(self: Pin<&Self>) -> impl Clone + '_ { self } + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.nll.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.nll.stderr new file mode 100644 index 00000000000..e53d91c3604 --- /dev/null +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.nll.stderr @@ -0,0 +1,46 @@ +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:8:45 + | +LL | async fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f } + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:8:50 + | +LL | async fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f } + | - ^^^^^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + | | + | lifetime `'_` defined here + | lifetime `'_` defined here + +error: lifetime may not live long enough + --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:11:73 + | +LL | async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) } + | - ^^^^^^^^^^^^^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + | | + | lifetime `'_` defined here + | lifetime `'_` defined here + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:17:58 + | +LL | async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg } + | ^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:17:62 + | +LL | async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg } + | -- - ^^^^^^^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'a` + | | | + | | lifetime `'_` defined here + | lifetime `'a` defined here + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.rs b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.rs new file mode 100644 index 00000000000..f42337d5340 --- /dev/null +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.rs @@ -0,0 +1,20 @@ +// edition:2018 + +use std::pin::Pin; + +struct Foo; + +impl Foo { + async fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f } + //~^ ERROR lifetime mismatch + + async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) } + //~^ ERROR lifetime mismatch +} + +type Alias<T> = Pin<T>; +impl Foo { + async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg } //~ ERROR E0623 +} + +fn main() {} diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.stderr new file mode 100644 index 00000000000..57ad026bdcf --- /dev/null +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch-async.stderr @@ -0,0 +1,29 @@ +error[E0623]: lifetime mismatch + --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:8:45 + | +LL | async fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f } + | ---- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:11:55 + | +LL | async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) } + | ----- ^^^^^^^^^^^^^^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:17:58 + | +LL | async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg } + | ----- ^^^ + | | | + | | ...but data from `arg` is returned here + | this parameter and the return type are declared with different lifetimes... + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/self/elision/README.md b/src/test/ui/self/elision/README.md index 7ace2e0c890..3bd7a6c00b2 100644 --- a/src/test/ui/self/elision/README.md +++ b/src/test/ui/self/elision/README.md @@ -42,3 +42,34 @@ In each case, we test the following patterns: - `self: Box<Pin<XXX>>` In the non-reference cases, `Pin` causes errors so we substitute `Rc`. + +### `async fn` + +For each of the tests above we also check that `async fn` behaves as an `fn` would. +These tests are in files named `*-async.rs`. + +Legends: +- ✓ ⟹ Yes / Pass +- X ⟹ No +- α ⟹ lifetime mismatch +- β ⟹ cannot infer an appropriate lifetime +- γ ⟹ missing lifetime specifier + +| `async` file | Pass? | Conforms to `fn`? | How does it diverge? <br/> `fn` ⟶ `async fn` | +| --- | --- | --- | --- | +| `self-async.rs` | ✓ | ✓ | N/A | +| `struct-async.rs`| ✓ | ✓ | N/A | +| `alias-async.rs`| ✓ | ✓ | N/A | +| `assoc-async.rs`| ✓ | ✓ | N/A | +| `ref-self-async.rs` | X | ✓ | N/A | +| `ref-mut-self-async.rs` | X | ✓ | N/A | +| `ref-struct-async.rs` | X | ✓ | N/A | +| `ref-mut-struct-async.rs` | X | ✓ | N/A | +| `ref-alias-async.rs` | ✓ | ✓ | N/A | +| `ref-assoc-async.rs` | ✓ | ✓ | N/A | +| `ref-mut-alias-async.rs` | ✓ | ✓ | N/A | +| `lt-self-async.rs` | ✓ | ✓ | N/A +| `lt-struct-async.rs` | ✓ | ✓ | N/A +| `lt-alias-async.rs` | ✓ | ✓ | N/A +| `lt-assoc-async.rs` | ✓ | ✓ | N/A +| `lt-ref-self-async.rs` | X | ✓ | N/A | diff --git a/src/test/ui/self/elision/alias-async.rs b/src/test/ui/self/elision/alias-async.rs new file mode 100644 index 00000000000..9743c139096 --- /dev/null +++ b/src/test/ui/self/elision/alias-async.rs @@ -0,0 +1,37 @@ +// check-pass +// edition:2018 + +#![feature(arbitrary_self_types)] +#![allow(non_snake_case)] + +use std::rc::Rc; + +struct Struct { } + +type Alias = Struct; + +impl Struct { + // Test using an alias for `Struct`: + + async fn alias(self: Alias, f: &u32) -> &u32 { + f + } + + async fn box_Alias(self: Box<Alias>, f: &u32) -> &u32 { + f + } + + async fn rc_Alias(self: Rc<Alias>, f: &u32) -> &u32 { + f + } + + async fn box_box_Alias(self: Box<Box<Alias>>, f: &u32) -> &u32 { + f + } + + async fn box_rc_Alias(self: Box<Rc<Alias>>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/assoc-async.rs b/src/test/ui/self/elision/assoc-async.rs new file mode 100644 index 00000000000..fa5968de5ac --- /dev/null +++ b/src/test/ui/self/elision/assoc-async.rs @@ -0,0 +1,41 @@ +// check-pass +// edition:2018 + +#![feature(arbitrary_self_types)] +#![allow(non_snake_case)] + +use std::rc::Rc; + +trait Trait { + type AssocType; +} + +struct Struct { } + +impl Trait for Struct { + type AssocType = Self; +} + +impl Struct { + async fn assoc(self: <Struct as Trait>::AssocType, f: &u32) -> &u32 { + f + } + + async fn box_AssocType(self: Box<<Struct as Trait>::AssocType>, f: &u32) -> &u32 { + f + } + + async fn rc_AssocType(self: Rc<<Struct as Trait>::AssocType>, f: &u32) -> &u32 { + f + } + + async fn box_box_AssocType(self: Box<Box<<Struct as Trait>::AssocType>>, f: &u32) -> &u32 { + f + } + + async fn box_rc_AssocType(self: Box<Rc<<Struct as Trait>::AssocType>>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/lt-alias-async.rs b/src/test/ui/self/elision/lt-alias-async.rs new file mode 100644 index 00000000000..cc5badaaa6e --- /dev/null +++ b/src/test/ui/self/elision/lt-alias-async.rs @@ -0,0 +1,39 @@ +// check-pass +// edition:2018 + +#![feature(arbitrary_self_types)] +#![allow(non_snake_case)] + +use std::rc::Rc; + +struct Struct<'a> { x: &'a u32 } + +type Alias<'a> = Struct<'a>; + +impl<'a> Alias<'a> { + async fn take_self(self, f: &u32) -> &u32 { + f + } + + async fn take_Alias(self: Alias<'a>, f: &u32) -> &u32 { + f + } + + async fn take_Box_Alias(self: Box<Alias<'a>>, f: &u32) -> &u32 { + f + } + + async fn take_Box_Box_Alias(self: Box<Box<Alias<'a>>>, f: &u32) -> &u32 { + f + } + + async fn take_Rc_Alias(self: Rc<Alias<'a>>, f: &u32) -> &u32 { + f + } + + async fn take_Box_Rc_Alias(self: Box<Rc<Alias<'a>>>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/lt-assoc-async.rs b/src/test/ui/self/elision/lt-assoc-async.rs new file mode 100644 index 00000000000..f060800e4da --- /dev/null +++ b/src/test/ui/self/elision/lt-assoc-async.rs @@ -0,0 +1,51 @@ +// check-pass +// edition:2018 + +#![feature(arbitrary_self_types)] +#![allow(non_snake_case)] + +use std::rc::Rc; + +trait Trait { + type AssocType; +} + +struct Struct<'a> { x: &'a u32 } + +impl<'a> Trait for Struct<'a> { + type AssocType = Self; +} + +impl<'a> Struct<'a> { + async fn take_self(self, f: &u32) -> &u32 { + f + } + + async fn take_AssocType(self: <Struct<'a> as Trait>::AssocType, f: &u32) -> &u32 { + f + } + + async fn take_Box_AssocType(self: Box<<Struct<'a> as Trait>::AssocType>, f: &u32) -> &u32 { + f + } + + async fn take_Box_Box_AssocType( + self: Box<Box<<Struct<'a> as Trait>::AssocType>>, + f: &u32 + ) -> &u32 { + f + } + + async fn take_Rc_AssocType(self: Rc<<Struct<'a> as Trait>::AssocType>, f: &u32) -> &u32 { + f + } + + async fn take_Box_Rc_AssocType( + self: Box<Rc<<Struct<'a> as Trait>::AssocType>>, + f: &u32 + ) -> &u32 { + f + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/lt-ref-self-async.nll.stderr b/src/test/ui/self/elision/lt-ref-self-async.nll.stderr new file mode 100644 index 00000000000..998178dde1d --- /dev/null +++ b/src/test/ui/self/elision/lt-ref-self-async.nll.stderr @@ -0,0 +1,123 @@ +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/lt-ref-self-async.rs:13:42 + | +LL | async fn ref_self(&self, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#23r + +error: lifetime may not live long enough + --> $DIR/lt-ref-self-async.rs:13:47 + | +LL | async fn ref_self(&self, f: &u32) -> &u32 { + | _______________________-_______________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/lt-ref-self-async.rs:19:48 + | +LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#23r + +error: lifetime may not live long enough + --> $DIR/lt-ref-self-async.rs:19:53 + | +LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 { + | _____________________________-_______________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/lt-ref-self-async.rs:23:57 + | +LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#23r + +error: lifetime may not live long enough + --> $DIR/lt-ref-self-async.rs:23:62 + | +LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { + | _____________________________________-________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/lt-ref-self-async.rs:27:57 + | +LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#23r + +error: lifetime may not live long enough + --> $DIR/lt-ref-self-async.rs:27:62 + | +LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { + | _____________________________________-________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/lt-ref-self-async.rs:31:66 + | +LL | async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#23r + +error: lifetime may not live long enough + --> $DIR/lt-ref-self-async.rs:31:71 + | +LL | async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 { + | _____________________________________________-_________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/lt-ref-self-async.rs:35:62 + | +LL | async fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#23r + +error: lifetime may not live long enough + --> $DIR/lt-ref-self-async.rs:35:67 + | +LL | async fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 { + | _________________________________________-_________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error: aborting due to 12 previous errors + +For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/self/elision/lt-ref-self-async.rs b/src/test/ui/self/elision/lt-ref-self-async.rs new file mode 100644 index 00000000000..e3ca0c2e2dd --- /dev/null +++ b/src/test/ui/self/elision/lt-ref-self-async.rs @@ -0,0 +1,40 @@ +// edition:2018 + +#![feature(arbitrary_self_types)] +#![allow(non_snake_case)] + +use std::pin::Pin; + +struct Struct<'a> { data: &'a u32 } + +impl<'a> Struct<'a> { + // Test using `&self` sugar: + + async fn ref_self(&self, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } + + // Test using `&Self` explicitly: + + async fn ref_Self(self: &Self, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } + + async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } + + async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } + + async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } + + async fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/lt-ref-self-async.stderr b/src/test/ui/self/elision/lt-ref-self-async.stderr new file mode 100644 index 00000000000..2bc64bdf1f7 --- /dev/null +++ b/src/test/ui/self/elision/lt-ref-self-async.stderr @@ -0,0 +1,56 @@ +error[E0623]: lifetime mismatch + --> $DIR/lt-ref-self-async.rs:13:42 + | +LL | async fn ref_self(&self, f: &u32) -> &u32 { + | ----- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/lt-ref-self-async.rs:19:48 + | +LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 { + | ----- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/lt-ref-self-async.rs:23:57 + | +LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { + | ----- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/lt-ref-self-async.rs:27:57 + | +LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { + | ----- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/lt-ref-self-async.rs:31:66 + | +LL | async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 { + | ----- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/lt-ref-self-async.rs:35:62 + | +LL | async fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 { + | ----- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error: aborting due to 6 previous errors + diff --git a/src/test/ui/self/elision/lt-self-async.rs b/src/test/ui/self/elision/lt-self-async.rs new file mode 100644 index 00000000000..42647b82ef8 --- /dev/null +++ b/src/test/ui/self/elision/lt-self-async.rs @@ -0,0 +1,50 @@ +// check-pass +// edition:2018 + +#![feature(arbitrary_self_types)] +#![allow(non_snake_case)] + +use std::pin::Pin; +use std::rc::Rc; + +struct Struct<'a> { + x: &'a u32 +} + +impl<'a> Struct<'a> { + async fn take_self(self, f: &u32) -> &u32 { + f + } + + async fn take_Self(self: Self, f: &u32) -> &u32 { + f + } + + async fn take_Box_Self(self: Box<Self>, f: &u32) -> &u32 { + f + } + + async fn take_Box_Box_Self(self: Box<Box<Self>>, f: &u32) -> &u32 { + f + } + + async fn take_Rc_Self(self: Rc<Self>, f: &u32) -> &u32 { + f + } + + async fn take_Box_Rc_Self(self: Box<Rc<Self>>, f: &u32) -> &u32 { + f + } + + // N/A + //fn take_Pin_Self(self: Pin<Self>, f: &u32) -> &u32 { + // f + //} + + // N/A + //fn take_Box_Pin_Self(self: Box<Pin<Self>>, f: &u32) -> &u32 { + // f + //} +} + +fn main() { } diff --git a/src/test/ui/self/elision/lt-struct-async.rs b/src/test/ui/self/elision/lt-struct-async.rs new file mode 100644 index 00000000000..dc5a53b89d7 --- /dev/null +++ b/src/test/ui/self/elision/lt-struct-async.rs @@ -0,0 +1,37 @@ +// check-pass +// edition:2018 + +#![feature(arbitrary_self_types)] +#![allow(non_snake_case)] + +use std::rc::Rc; + +struct Struct<'a> { x: &'a u32 } + +impl<'a> Struct<'a> { + async fn take_self(self, f: &u32) -> &u32 { + f + } + + async fn take_Struct(self: Struct<'a>, f: &u32) -> &u32 { + f + } + + async fn take_Box_Struct(self: Box<Struct<'a>>, f: &u32) -> &u32 { + f + } + + async fn take_Box_Box_Struct(self: Box<Box<Struct<'a>>>, f: &u32) -> &u32 { + f + } + + async fn take_Rc_Struct(self: Rc<Struct<'a>>, f: &u32) -> &u32 { + f + } + + async fn take_Box_Rc_Struct(self: Box<Rc<Struct<'a>>>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/multiple-ref-self-async.rs b/src/test/ui/self/elision/multiple-ref-self-async.rs new file mode 100644 index 00000000000..be073c6edba --- /dev/null +++ b/src/test/ui/self/elision/multiple-ref-self-async.rs @@ -0,0 +1,44 @@ +// check-pass +// edition:2018 + +#![feature(arbitrary_self_types)] +#![allow(non_snake_case)] + +use std::marker::PhantomData; +use std::ops::Deref; +use std::pin::Pin; + +struct Struct { } + +struct Wrap<T, P>(T, PhantomData<P>); + +impl<T, P> Deref for Wrap<T, P> { + type Target = T; + fn deref(&self) -> &T { &self.0 } +} + +impl Struct { + // Test using multiple `&Self`: + + async fn wrap_ref_Self_ref_Self(self: Wrap<&Self, &Self>, f: &u8) -> &u8 { + f + } + + async fn box_wrap_ref_Self_ref_Self(self: Box<Wrap<&Self, &Self>>, f: &u32) -> &u32 { + f + } + + async fn pin_wrap_ref_Self_ref_Self(self: Pin<Wrap<&Self, &Self>>, f: &u32) -> &u32 { + f + } + + async fn box_box_wrap_ref_Self_ref_Self(self: Box<Box<Wrap<&Self, &Self>>>, f: &u32) -> &u32 { + f + } + + async fn box_pin_wrap_ref_Self_ref_Self(self: Box<Pin<Wrap<&Self, &Self>>>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/ref-alias-async.rs b/src/test/ui/self/elision/ref-alias-async.rs new file mode 100644 index 00000000000..4b02c2fd00c --- /dev/null +++ b/src/test/ui/self/elision/ref-alias-async.rs @@ -0,0 +1,40 @@ +// edition:2018 +// check-pass + +#![feature(arbitrary_self_types)] +#![allow(non_snake_case)] + +use std::pin::Pin; + +struct Struct { } + +type Alias = Struct; + +impl Struct { + // Test using an alias for `Struct`: + // + // FIXME. We currently fail to recognize this as the self type, which + // feels like a bug. + + async fn ref_Alias(self: &Alias, f: &u32) -> &u32 { + f + } + + async fn box_ref_Alias(self: Box<&Alias>, f: &u32) -> &u32 { + f + } + + async fn pin_ref_Alias(self: Pin<&Alias>, f: &u32) -> &u32 { + f + } + + async fn box_box_ref_Alias(self: Box<Box<&Alias>>, f: &u32) -> &u32 { + f + } + + async fn box_pin_ref_Alias(self: Box<Pin<&Alias>>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/ref-assoc-async.rs b/src/test/ui/self/elision/ref-assoc-async.rs new file mode 100644 index 00000000000..258e27b7cb3 --- /dev/null +++ b/src/test/ui/self/elision/ref-assoc-async.rs @@ -0,0 +1,41 @@ +// edition:2018 +// check-pass + +#![feature(arbitrary_self_types)] +#![allow(non_snake_case)] + +use std::pin::Pin; + +trait Trait { + type AssocType; +} + +struct Struct { } + +impl Trait for Struct { + type AssocType = Self; +} + +impl Struct { + async fn ref_AssocType(self: &<Struct as Trait>::AssocType, f: &u32) -> &u32 { + f + } + + async fn box_ref_AssocType(self: Box<&<Struct as Trait>::AssocType>, f: &u32) -> &u32 { + f + } + + async fn pin_ref_AssocType(self: Pin<&<Struct as Trait>::AssocType>, f: &u32) -> &u32 { + f + } + + async fn box_box_ref_AssocType(self: Box<Box<&<Struct as Trait>::AssocType>>, f: &u32) -> &u32 { + f + } + + async fn box_pin_ref_AssocType(self: Box<Pin<&<Struct as Trait>::AssocType>>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/ref-mut-alias-async.rs b/src/test/ui/self/elision/ref-mut-alias-async.rs new file mode 100644 index 00000000000..5f9ccf3bc7f --- /dev/null +++ b/src/test/ui/self/elision/ref-mut-alias-async.rs @@ -0,0 +1,37 @@ +// edition:2018 +// check-pass + +#![feature(arbitrary_self_types)] +#![allow(non_snake_case)] + +use std::pin::Pin; + +struct Struct { } + +type Alias = Struct; + +impl Struct { + // Test using an alias for `Struct`: + + async fn ref_Alias(self: &mut Alias, f: &u32) -> &u32 { + f + } + + async fn box_ref_Alias(self: Box<&mut Alias>, f: &u32) -> &u32 { + f + } + + async fn pin_ref_Alias(self: Pin<&mut Alias>, f: &u32) -> &u32 { + f + } + + async fn box_box_ref_Alias(self: Box<Box<&mut Alias>>, f: &u32) -> &u32 { + f + } + + async fn box_pin_ref_Alias(self: Box<Pin<&mut Alias>>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/ref-mut-self-async.nll.stderr b/src/test/ui/self/elision/ref-mut-self-async.nll.stderr new file mode 100644 index 00000000000..97bc80509df --- /dev/null +++ b/src/test/ui/self/elision/ref-mut-self-async.nll.stderr @@ -0,0 +1,123 @@ +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ref-mut-self-async.rs:13:46 + | +LL | async fn ref_self(&mut self, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/ref-mut-self-async.rs:13:51 + | +LL | async fn ref_self(&mut self, f: &u32) -> &u32 { + | _______________________-___________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ref-mut-self-async.rs:19:52 + | +LL | async fn ref_Self(self: &mut Self, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/ref-mut-self-async.rs:19:57 + | +LL | async fn ref_Self(self: &mut Self, f: &u32) -> &u32 { + | _____________________________-___________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ref-mut-self-async.rs:23:61 + | +LL | async fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/ref-mut-self-async.rs:23:66 + | +LL | async fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 { + | _____________________________________-____________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ref-mut-self-async.rs:27:61 + | +LL | async fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/ref-mut-self-async.rs:27:66 + | +LL | async fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 { + | _____________________________________-____________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ref-mut-self-async.rs:31:70 + | +LL | async fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/ref-mut-self-async.rs:31:75 + | +LL | async fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 { + | _____________________________________________-_____________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ref-mut-self-async.rs:35:70 + | +LL | async fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/ref-mut-self-async.rs:35:75 + | +LL | async fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 { + | _____________________________________________-_____________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error: aborting due to 12 previous errors + +For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/self/elision/ref-mut-self-async.rs b/src/test/ui/self/elision/ref-mut-self-async.rs new file mode 100644 index 00000000000..2ca14800a75 --- /dev/null +++ b/src/test/ui/self/elision/ref-mut-self-async.rs @@ -0,0 +1,40 @@ +// edition:2018 + +#![feature(arbitrary_self_types)] +#![allow(non_snake_case)] + +use std::pin::Pin; + +struct Struct { } + +impl Struct { + // Test using `&mut self` sugar: + + async fn ref_self(&mut self, f: &u32) -> &u32 { //~ ERROR lifetime mismatch + f + } + + // Test using `&mut Self` explicitly: + + async fn ref_Self(self: &mut Self, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } + + async fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } + + async fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } + + async fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } + + async fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/ref-mut-self-async.stderr b/src/test/ui/self/elision/ref-mut-self-async.stderr new file mode 100644 index 00000000000..39a1b30ca53 --- /dev/null +++ b/src/test/ui/self/elision/ref-mut-self-async.stderr @@ -0,0 +1,56 @@ +error[E0623]: lifetime mismatch + --> $DIR/ref-mut-self-async.rs:13:46 + | +LL | async fn ref_self(&mut self, f: &u32) -> &u32 { + | --------- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/ref-mut-self-async.rs:19:52 + | +LL | async fn ref_Self(self: &mut Self, f: &u32) -> &u32 { + | --------- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/ref-mut-self-async.rs:23:61 + | +LL | async fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 { + | --------- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/ref-mut-self-async.rs:27:61 + | +LL | async fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 { + | --------- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/ref-mut-self-async.rs:31:70 + | +LL | async fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 { + | --------- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/ref-mut-self-async.rs:35:70 + | +LL | async fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 { + | --------- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error: aborting due to 6 previous errors + diff --git a/src/test/ui/self/elision/ref-mut-struct-async.nll.stderr b/src/test/ui/self/elision/ref-mut-struct-async.nll.stderr new file mode 100644 index 00000000000..2905a022e5d --- /dev/null +++ b/src/test/ui/self/elision/ref-mut-struct-async.nll.stderr @@ -0,0 +1,103 @@ +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ref-mut-struct-async.rs:13:56 + | +LL | async fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/ref-mut-struct-async.rs:13:61 + | +LL | async fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 { + | _______________________________-_____________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ref-mut-struct-async.rs:17:65 + | +LL | async fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/ref-mut-struct-async.rs:17:70 + | +LL | async fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 { + | _______________________________________-______________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ref-mut-struct-async.rs:21:65 + | +LL | async fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/ref-mut-struct-async.rs:21:70 + | +LL | async fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 { + | _______________________________________-______________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ref-mut-struct-async.rs:25:74 + | +LL | async fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/ref-mut-struct-async.rs:25:79 + | +LL | async fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 { + | _______________________________________________-_______________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ref-mut-struct-async.rs:29:74 + | +LL | async fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/ref-mut-struct-async.rs:29:79 + | +LL | async fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 { + | _______________________________________________-_______________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error: aborting due to 10 previous errors + +For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/self/elision/ref-mut-struct-async.rs b/src/test/ui/self/elision/ref-mut-struct-async.rs new file mode 100644 index 00000000000..a671116de25 --- /dev/null +++ b/src/test/ui/self/elision/ref-mut-struct-async.rs @@ -0,0 +1,34 @@ +// edition:2018 + +#![feature(arbitrary_self_types)] +#![allow(non_snake_case)] + +use std::pin::Pin; + +struct Struct { } + +impl Struct { + // Test using `&mut Struct` explicitly: + + async fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } + + async fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } + + async fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } + + async fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } + + async fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/ref-mut-struct-async.stderr b/src/test/ui/self/elision/ref-mut-struct-async.stderr new file mode 100644 index 00000000000..fe4a636ada6 --- /dev/null +++ b/src/test/ui/self/elision/ref-mut-struct-async.stderr @@ -0,0 +1,47 @@ +error[E0623]: lifetime mismatch + --> $DIR/ref-mut-struct-async.rs:13:56 + | +LL | async fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 { + | ----------- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/ref-mut-struct-async.rs:17:65 + | +LL | async fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 { + | ----------- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/ref-mut-struct-async.rs:21:65 + | +LL | async fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 { + | ----------- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/ref-mut-struct-async.rs:25:74 + | +LL | async fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 { + | ----------- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/ref-mut-struct-async.rs:29:74 + | +LL | async fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 { + | ----------- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error: aborting due to 5 previous errors + diff --git a/src/test/ui/self/elision/ref-self-async.nll.stderr b/src/test/ui/self/elision/ref-self-async.nll.stderr new file mode 100644 index 00000000000..0eee56654f7 --- /dev/null +++ b/src/test/ui/self/elision/ref-self-async.nll.stderr @@ -0,0 +1,143 @@ +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ref-self-async.rs:22:42 + | +LL | async fn ref_self(&self, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/ref-self-async.rs:22:47 + | +LL | async fn ref_self(&self, f: &u32) -> &u32 { + | _______________________-_______________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ref-self-async.rs:28:48 + | +LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/ref-self-async.rs:28:53 + | +LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 { + | _____________________________-_______________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ref-self-async.rs:32:57 + | +LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/ref-self-async.rs:32:62 + | +LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { + | _____________________________________-________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ref-self-async.rs:36:57 + | +LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/ref-self-async.rs:36:62 + | +LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { + | _____________________________________-________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ref-self-async.rs:40:66 + | +LL | async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/ref-self-async.rs:40:71 + | +LL | async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 { + | _____________________________________________-_________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ref-self-async.rs:44:66 + | +LL | async fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/ref-self-async.rs:44:71 + | +LL | async fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 { + | _____________________________________________-_________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ref-self-async.rs:48:69 + | +LL | async fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 { + | ^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/ref-self-async.rs:48:73 + | +LL | async fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 { + | ____________________________________________-____________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error: aborting due to 14 previous errors + +For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/self/elision/ref-self-async.rs b/src/test/ui/self/elision/ref-self-async.rs new file mode 100644 index 00000000000..06f3b127b21 --- /dev/null +++ b/src/test/ui/self/elision/ref-self-async.rs @@ -0,0 +1,53 @@ +// edition:2018 + +#![feature(arbitrary_self_types)] +#![allow(non_snake_case)] + +use std::marker::PhantomData; +use std::ops::Deref; +use std::pin::Pin; + +struct Struct { } + +struct Wrap<T, P>(T, PhantomData<P>); + +impl<T, P> Deref for Wrap<T, P> { + type Target = T; + fn deref(&self) -> &T { &self.0 } +} + +impl Struct { + // Test using `&self` sugar: + + async fn ref_self(&self, f: &u32) -> &u32 { //~ ERROR lifetime mismatch + f + } + + // Test using `&Self` explicitly: + + async fn ref_Self(self: &Self, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } + + async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } + + async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } + + async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } + + async fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } + + async fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 { + f //~^ ERROR lifetime mismatch + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/ref-self-async.stderr b/src/test/ui/self/elision/ref-self-async.stderr new file mode 100644 index 00000000000..2f9e2a01e34 --- /dev/null +++ b/src/test/ui/self/elision/ref-self-async.stderr @@ -0,0 +1,65 @@ +error[E0623]: lifetime mismatch + --> $DIR/ref-self-async.rs:22:42 + | +LL | async fn ref_self(&self, f: &u32) -> &u32 { + | ----- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/ref-self-async.rs:28:48 + | +LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 { + | ----- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/ref-self-async.rs:32:57 + | +LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { + | ----- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/ref-self-async.rs:36:57 + | +LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { + | ----- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/ref-self-async.rs:40:66 + | +LL | async fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 { + | ----- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/ref-self-async.rs:44:66 + | +LL | async fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 { + | ----- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/ref-self-async.rs:48:69 + | +LL | async fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 { + | ----- ^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error: aborting due to 7 previous errors + diff --git a/src/test/ui/self/elision/ref-struct-async.nll.stderr b/src/test/ui/self/elision/ref-struct-async.nll.stderr new file mode 100644 index 00000000000..8508e42264b --- /dev/null +++ b/src/test/ui/self/elision/ref-struct-async.nll.stderr @@ -0,0 +1,103 @@ +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ref-struct-async.rs:13:52 + | +LL | async fn ref_Struct(self: &Struct, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/ref-struct-async.rs:13:57 + | +LL | async fn ref_Struct(self: &Struct, f: &u32) -> &u32 { + | _______________________________-_________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ref-struct-async.rs:17:61 + | +LL | async fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/ref-struct-async.rs:17:66 + | +LL | async fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 { + | _______________________________________-__________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ref-struct-async.rs:21:61 + | +LL | async fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/ref-struct-async.rs:21:66 + | +LL | async fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 { + | _______________________________________-__________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ref-struct-async.rs:25:70 + | +LL | async fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/ref-struct-async.rs:25:75 + | +LL | async fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 { + | _______________________________________________-___________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/ref-struct-async.rs:29:66 + | +LL | async fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 { + | ^^^^ + | + = note: hidden type `impl std::future::Future` captures lifetime '_#15r + +error: lifetime may not live long enough + --> $DIR/ref-struct-async.rs:29:71 + | +LL | async fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 { + | ___________________________________________-___________________________^ + | | | + | | lifetime `'_` defined here + | | lifetime `'_` defined here +LL | | f +LL | | } + | |_____^ function was supposed to return data with lifetime `'_` but it is returning data with lifetime `'_` + +error: aborting due to 10 previous errors + +For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/self/elision/ref-struct-async.rs b/src/test/ui/self/elision/ref-struct-async.rs new file mode 100644 index 00000000000..94eaeedc734 --- /dev/null +++ b/src/test/ui/self/elision/ref-struct-async.rs @@ -0,0 +1,34 @@ +// edition:2018 + +#![feature(arbitrary_self_types)] +#![allow(non_snake_case)] + +use std::pin::Pin; + +struct Struct { } + +impl Struct { + // Test using `&Struct` explicitly: + + async fn ref_Struct(self: &Struct, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } + + async fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } + + async fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } + + async fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } + + async fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 { + f //~^ ERROR lifetime mismatch + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/ref-struct-async.stderr b/src/test/ui/self/elision/ref-struct-async.stderr new file mode 100644 index 00000000000..222e27ebf0d --- /dev/null +++ b/src/test/ui/self/elision/ref-struct-async.stderr @@ -0,0 +1,47 @@ +error[E0623]: lifetime mismatch + --> $DIR/ref-struct-async.rs:13:52 + | +LL | async fn ref_Struct(self: &Struct, f: &u32) -> &u32 { + | ------- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/ref-struct-async.rs:17:61 + | +LL | async fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 { + | ------- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/ref-struct-async.rs:21:61 + | +LL | async fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 { + | ------- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/ref-struct-async.rs:25:70 + | +LL | async fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 { + | ------- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error[E0623]: lifetime mismatch + --> $DIR/ref-struct-async.rs:29:66 + | +LL | async fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 { + | ------- ^^^^ + | | | + | | ...but data from `f` is returned here + | this parameter and the return type are declared with different lifetimes... + +error: aborting due to 5 previous errors + diff --git a/src/test/ui/self/elision/self-async.rs b/src/test/ui/self/elision/self-async.rs new file mode 100644 index 00000000000..e1379bfaf2e --- /dev/null +++ b/src/test/ui/self/elision/self-async.rs @@ -0,0 +1,37 @@ +// check-pass +// edition:2018 + +#![feature(arbitrary_self_types)] +#![allow(non_snake_case)] + +use std::rc::Rc; + +struct Struct { } + +impl Struct { + async fn take_self(self, f: &u32) -> &u32 { + f + } + + async fn take_Self(self: Self, f: &u32) -> &u32 { + f + } + + async fn take_Box_Self(self: Box<Self>, f: &u32) -> &u32 { + f + } + + async fn take_Box_Box_Self(self: Box<Box<Self>>, f: &u32) -> &u32 { + f + } + + async fn take_Rc_Self(self: Rc<Self>, f: &u32) -> &u32 { + f + } + + async fn take_Box_Rc_Self(self: Box<Rc<Self>>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/src/test/ui/self/elision/struct-async.rs b/src/test/ui/self/elision/struct-async.rs new file mode 100644 index 00000000000..4a38a2164c8 --- /dev/null +++ b/src/test/ui/self/elision/struct-async.rs @@ -0,0 +1,33 @@ +// check-pass +// edition:2018 + +#![feature(arbitrary_self_types)] +#![allow(non_snake_case)] + +use std::rc::Rc; + +struct Struct { } + +impl Struct { + async fn ref_Struct(self: Struct, f: &u32) -> &u32 { + f + } + + async fn box_Struct(self: Box<Struct>, f: &u32) -> &u32 { + f + } + + async fn rc_Struct(self: Rc<Struct>, f: &u32) -> &u32 { + f + } + + async fn box_box_Struct(self: Box<Box<Struct>>, f: &u32) -> &u32 { + f + } + + async fn box_rc_Struct(self: Box<Rc<Struct>>, f: &u32) -> &u32 { + f + } +} + +fn main() { } diff --git a/src/test/ui/self/self_lifetime-async.rs b/src/test/ui/self/self_lifetime-async.rs new file mode 100644 index 00000000000..c3c6e56582d --- /dev/null +++ b/src/test/ui/self/self_lifetime-async.rs @@ -0,0 +1,14 @@ +// check-pass +// edition:2018 + +struct Foo<'a>(&'a ()); +impl<'a> Foo<'a> { + async fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 } +} + +type Alias = Foo<'static>; +impl Alias { + async fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg } +} + +fn main() {} diff --git a/src/test/ui/shadowed/shadowed-type-parameter.rs b/src/test/ui/shadowed/shadowed-type-parameter.rs index ba9f3abcf7a..e74620f8900 100644 --- a/src/test/ui/shadowed/shadowed-type-parameter.rs +++ b/src/test/ui/shadowed/shadowed-type-parameter.rs @@ -6,7 +6,7 @@ struct Foo<T>(T); impl<T> Foo<T> { fn shadow_in_method<T>(&self) {} - //~^ ERROR type parameter `T` shadows another type parameter + //~^ ERROR the name `T` is already used fn not_shadow_in_item<U>(&self) { struct Bar<T, U>(T,U); // not a shadow, separate item @@ -18,10 +18,10 @@ trait Bar<T> { fn dummy(&self) -> T; fn shadow_in_required<T>(&self); - //~^ ERROR type parameter `T` shadows another type parameter + //~^ ERROR the name `T` is already used fn shadow_in_provided<T>(&self) {} - //~^ ERROR type parameter `T` shadows another type parameter + //~^ ERROR the name `T` is already used fn not_shadow_in_required<U>(&self); fn not_shadow_in_provided<U>(&self) {} diff --git a/src/test/ui/shadowed/shadowed-type-parameter.stderr b/src/test/ui/shadowed/shadowed-type-parameter.stderr index 6b4d1fae3de..0ea82f983f1 100644 --- a/src/test/ui/shadowed/shadowed-type-parameter.stderr +++ b/src/test/ui/shadowed/shadowed-type-parameter.stderr @@ -1,29 +1,29 @@ -error[E0194]: type parameter `T` shadows another type parameter of the same name +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters + --> $DIR/shadowed-type-parameter.rs:8:25 + | +LL | impl<T> Foo<T> { + | - first use of `T` +LL | fn shadow_in_method<T>(&self) {} + | ^ already used + +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters --> $DIR/shadowed-type-parameter.rs:20:27 | LL | trait Bar<T> { - | - first `T` declared here + | - first use of `T` ... LL | fn shadow_in_required<T>(&self); - | ^ shadows another type parameter + | ^ already used -error[E0194]: type parameter `T` shadows another type parameter of the same name +error[E0403]: the name `T` is already used for a generic parameter in this item's generic parameters --> $DIR/shadowed-type-parameter.rs:23:27 | LL | trait Bar<T> { - | - first `T` declared here + | - first use of `T` ... LL | fn shadow_in_provided<T>(&self) {} - | ^ shadows another type parameter - -error[E0194]: type parameter `T` shadows another type parameter of the same name - --> $DIR/shadowed-type-parameter.rs:8:25 - | -LL | impl<T> Foo<T> { - | - first `T` declared here -LL | fn shadow_in_method<T>(&self) {} - | ^ shadows another type parameter + | ^ already used error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0194`. +For more information about this error, try `rustc --explain E0403`. diff --git a/src/test/ui/specialization/defaultimpl/specialization-no-default.rs b/src/test/ui/specialization/defaultimpl/specialization-no-default.rs index 7ea79a9a7bf..37005f839d4 100644 --- a/src/test/ui/specialization/defaultimpl/specialization-no-default.rs +++ b/src/test/ui/specialization/defaultimpl/specialization-no-default.rs @@ -3,9 +3,7 @@ // Check a number of scenarios in which one impl tries to override another, // without correctly using `default`. -//////////////////////////////////////////////////////////////////////////////// // Test 1: one layer of specialization, multiple methods, missing `default` -//////////////////////////////////////////////////////////////////////////////// trait Foo { fn foo(&self); @@ -25,9 +23,7 @@ impl Foo for u32 { fn bar(&self) {} //~ ERROR E0520 } -//////////////////////////////////////////////////////////////////////////////// // Test 2: one layer of specialization, missing `default` on associated type -//////////////////////////////////////////////////////////////////////////////// trait Bar { type T; @@ -41,9 +37,7 @@ impl Bar for u8 { type T = (); //~ ERROR E0520 } -//////////////////////////////////////////////////////////////////////////////// // Test 3a: multiple layers of specialization, missing interior `default` -//////////////////////////////////////////////////////////////////////////////// trait Baz { fn baz(&self); @@ -61,10 +55,8 @@ impl Baz for i32 { fn baz(&self) {} //~ ERROR E0520 } -//////////////////////////////////////////////////////////////////////////////// // Test 3b: multiple layers of specialization, missing interior `default`, // redundant `default` in bottom layer. -//////////////////////////////////////////////////////////////////////////////// trait Redundant { fn redundant(&self); diff --git a/src/test/ui/specialization/defaultimpl/specialization-no-default.stderr b/src/test/ui/specialization/defaultimpl/specialization-no-default.stderr index 91690f64d94..13636b28b12 100644 --- a/src/test/ui/specialization/defaultimpl/specialization-no-default.stderr +++ b/src/test/ui/specialization/defaultimpl/specialization-no-default.stderr @@ -1,5 +1,5 @@ error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/specialization-no-default.rs:22:5 + --> $DIR/specialization-no-default.rs:20:5 | LL | / impl<T> Foo for T { LL | | fn foo(&self) {} @@ -13,7 +13,7 @@ LL | fn foo(&self) {} = note: to specialize, `foo` in the parent `impl` must be marked `default` error[E0520]: `bar` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/specialization-no-default.rs:25:5 + --> $DIR/specialization-no-default.rs:23:5 | LL | / impl<T> Foo for T { LL | | fn foo(&self) {} @@ -27,7 +27,7 @@ LL | fn bar(&self) {} = note: to specialize, `bar` in the parent `impl` must be marked `default` error[E0520]: `T` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/specialization-no-default.rs:41:5 + --> $DIR/specialization-no-default.rs:37:5 | LL | / impl<T> Bar for T { LL | | type T = u8; @@ -40,7 +40,7 @@ LL | type T = (); = note: to specialize, `T` in the parent `impl` must be marked `default` error[E0520]: `baz` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/specialization-no-default.rs:61:5 + --> $DIR/specialization-no-default.rs:55:5 | LL | / impl<T: Clone> Baz for T { LL | | fn baz(&self) {} @@ -53,7 +53,7 @@ LL | fn baz(&self) {} = note: to specialize, `baz` in the parent `impl` must be marked `default` error[E0520]: `redundant` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/specialization-no-default.rs:82:5 + --> $DIR/specialization-no-default.rs:74:5 | LL | / impl<T: Clone> Redundant for T { LL | | fn redundant(&self) {} diff --git a/src/test/ui/specialization/specialization-no-default.rs b/src/test/ui/specialization/specialization-no-default.rs index 29afbbd9bf2..57346b26d24 100644 --- a/src/test/ui/specialization/specialization-no-default.rs +++ b/src/test/ui/specialization/specialization-no-default.rs @@ -3,9 +3,7 @@ // Check a number of scenarios in which one impl tries to override another, // without correctly using `default`. -//////////////////////////////////////////////////////////////////////////////// // Test 1: one layer of specialization, multiple methods, missing `default` -//////////////////////////////////////////////////////////////////////////////// trait Foo { fn foo(&self); @@ -25,9 +23,7 @@ impl Foo for u32 { fn bar(&self) {} //~ ERROR E0520 } -//////////////////////////////////////////////////////////////////////////////// // Test 2: one layer of specialization, missing `default` on associated type -//////////////////////////////////////////////////////////////////////////////// trait Bar { type T; @@ -41,9 +37,7 @@ impl Bar for u8 { type T = (); //~ ERROR E0520 } -//////////////////////////////////////////////////////////////////////////////// // Test 3a: multiple layers of specialization, missing interior `default` -//////////////////////////////////////////////////////////////////////////////// trait Baz { fn baz(&self); @@ -61,10 +55,8 @@ impl Baz for i32 { fn baz(&self) {} //~ ERROR E0520 } -//////////////////////////////////////////////////////////////////////////////// // Test 3b: multiple layers of specialization, missing interior `default`, // redundant `default` in bottom layer. -//////////////////////////////////////////////////////////////////////////////// trait Redundant { fn redundant(&self); diff --git a/src/test/ui/specialization/specialization-no-default.stderr b/src/test/ui/specialization/specialization-no-default.stderr index c39986de38d..992e9abbd4c 100644 --- a/src/test/ui/specialization/specialization-no-default.stderr +++ b/src/test/ui/specialization/specialization-no-default.stderr @@ -1,5 +1,5 @@ error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/specialization-no-default.rs:22:5 + --> $DIR/specialization-no-default.rs:20:5 | LL | / impl<T> Foo for T { LL | | fn foo(&self) {} @@ -13,7 +13,7 @@ LL | fn foo(&self) {} = note: to specialize, `foo` in the parent `impl` must be marked `default` error[E0520]: `bar` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/specialization-no-default.rs:25:5 + --> $DIR/specialization-no-default.rs:23:5 | LL | / impl<T> Foo for T { LL | | fn foo(&self) {} @@ -27,7 +27,7 @@ LL | fn bar(&self) {} = note: to specialize, `bar` in the parent `impl` must be marked `default` error[E0520]: `T` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/specialization-no-default.rs:41:5 + --> $DIR/specialization-no-default.rs:37:5 | LL | / impl<T> Bar for T { LL | | type T = u8; @@ -40,7 +40,7 @@ LL | type T = (); = note: to specialize, `T` in the parent `impl` must be marked `default` error[E0520]: `baz` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/specialization-no-default.rs:61:5 + --> $DIR/specialization-no-default.rs:55:5 | LL | / impl<T: Clone> Baz for T { LL | | fn baz(&self) {} @@ -53,7 +53,7 @@ LL | fn baz(&self) {} = note: to specialize, `baz` in the parent `impl` must be marked `default` error[E0520]: `redundant` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/specialization-no-default.rs:82:5 + --> $DIR/specialization-no-default.rs:74:5 | LL | / impl<T: Clone> Redundant for T { LL | | fn redundant(&self) {} diff --git a/src/test/ui/structs/struct-path-self.rs b/src/test/ui/structs/struct-path-self.rs index 77880bfca40..c938ce8dad9 100644 --- a/src/test/ui/structs/struct-path-self.rs +++ b/src/test/ui/structs/struct-path-self.rs @@ -3,13 +3,13 @@ struct S; trait Tr { fn f() { let s = Self {}; - //~^ ERROR expected struct, variant or union type, found Self + //~^ ERROR expected struct, variant or union type, found type parameter let z = Self::<u8> {}; - //~^ ERROR expected struct, variant or union type, found Self + //~^ ERROR expected struct, variant or union type, found type parameter //~| ERROR type arguments are not allowed for this type match s { Self { .. } => {} - //~^ ERROR expected struct, variant or union type, found Self + //~^ ERROR expected struct, variant or union type, found type parameter } } } diff --git a/src/test/ui/structs/struct-path-self.stderr b/src/test/ui/structs/struct-path-self.stderr index 9eaa1f95bd0..8c88cacc69e 100644 --- a/src/test/ui/structs/struct-path-self.stderr +++ b/src/test/ui/structs/struct-path-self.stderr @@ -1,4 +1,4 @@ -error[E0071]: expected struct, variant or union type, found Self +error[E0071]: expected struct, variant or union type, found type parameter --> $DIR/struct-path-self.rs:5:17 | LL | let s = Self {}; @@ -10,13 +10,13 @@ error[E0109]: type arguments are not allowed for this type LL | let z = Self::<u8> {}; | ^^ type argument not allowed -error[E0071]: expected struct, variant or union type, found Self +error[E0071]: expected struct, variant or union type, found type parameter --> $DIR/struct-path-self.rs:7:17 | LL | let z = Self::<u8> {}; | ^^^^^^^^^^ not a struct -error[E0071]: expected struct, variant or union type, found Self +error[E0071]: expected struct, variant or union type, found type parameter --> $DIR/struct-path-self.rs:11:13 | LL | Self { .. } => {} diff --git a/src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.rs b/src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.rs index 1c1230346a5..bf0c1dc27ce 100644 --- a/src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.rs +++ b/src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.rs @@ -34,7 +34,7 @@ pub fn main() { let vs = &vx; let vsm = &mut vec![X(Y)]; - // -------- test for duplicate suggestions -------- + // test for duplicate suggestions let &(X(_t), X(_u)) = &(x.clone(), x.clone()); //~^ ERROR cannot move diff --git a/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.rs b/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.rs index 6e3879a4155..f1e043c30f2 100644 --- a/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.rs +++ b/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.rs @@ -22,7 +22,7 @@ fn move_into_fn() { let x = X(Y); - // -------- move into Fn -------- + // move into Fn consume_fn(|| { let X(_t) = x; @@ -89,7 +89,7 @@ fn move_into_fnmut() { let x = X(Y); - // -------- move into FnMut -------- + // move into FnMut consume_fnmut(|| { let X(_t) = x; diff --git a/src/test/ui/suggestions/dont-suggest-ref/simple.rs b/src/test/ui/suggestions/dont-suggest-ref/simple.rs index 69b303a6623..c53ac3d2cd6 100644 --- a/src/test/ui/suggestions/dont-suggest-ref/simple.rs +++ b/src/test/ui/suggestions/dont-suggest-ref/simple.rs @@ -33,7 +33,7 @@ pub fn main() { let vs = &vx; let vsm = &mut vec![X(Y)]; - // -------- move from Either/X place -------- + // move from Either/X place let X(_t) = *s; //~^ ERROR cannot move @@ -163,7 +163,7 @@ pub fn main() { // FIXME: should suggest removing `ref` too } - // -------- move from &Either/&X place -------- + // move from &Either/&X place let &X(_t) = s; //~^ ERROR cannot move @@ -251,7 +251,7 @@ pub fn main() { //~| HELP consider removing the `&mut` //~| SUGGESTION X(_t) - // -------- move from tuple of &Either/&X -------- + // move from tuple of &Either/&X // FIXME: These should have suggestions. @@ -283,7 +283,7 @@ pub fn main() { fn f4((&mut X(_t),): (&mut X,)) { } //~^ ERROR cannot move - // -------- move from &Either/&X value -------- + // move from &Either/&X value let &X(_t) = &x; //~^ ERROR cannot move diff --git a/src/test/ui/suggestions/dont-suggest-try_into-in-macros.rs b/src/test/ui/suggestions/dont-suggest-try_into-in-macros.rs new file mode 100644 index 00000000000..d625199c937 --- /dev/null +++ b/src/test/ui/suggestions/dont-suggest-try_into-in-macros.rs @@ -0,0 +1,3 @@ +fn main() { + assert_eq!(10u64, 10usize); //~ ERROR mismatched types +} diff --git a/src/test/ui/suggestions/dont-suggest-try_into-in-macros.stderr b/src/test/ui/suggestions/dont-suggest-try_into-in-macros.stderr new file mode 100644 index 00000000000..f04306997a9 --- /dev/null +++ b/src/test/ui/suggestions/dont-suggest-try_into-in-macros.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/dont-suggest-try_into-in-macros.rs:2:5 + | +LL | assert_eq!(10u64, 10usize); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected u64, found usize + | + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/issue-61226.rs b/src/test/ui/suggestions/issue-61226.rs new file mode 100644 index 00000000000..e83b0b4d630 --- /dev/null +++ b/src/test/ui/suggestions/issue-61226.rs @@ -0,0 +1,5 @@ +struct X {} +fn main() { + vec![X]; //… + //~^ ERROR expected value, found struct `X` +} diff --git a/src/test/ui/suggestions/issue-61226.stderr b/src/test/ui/suggestions/issue-61226.stderr new file mode 100644 index 00000000000..6d7d98ac6a1 --- /dev/null +++ b/src/test/ui/suggestions/issue-61226.stderr @@ -0,0 +1,9 @@ +error[E0423]: expected value, found struct `X` + --> $DIR/issue-61226.rs:3:10 + | +LL | vec![X]; //… + | ^ did you mean `X { /* fields */ }`? + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0423`. diff --git a/src/test/ui/suggestions/suggest-box.fixed b/src/test/ui/suggestions/suggest-box.fixed new file mode 100644 index 00000000000..3de02cd0bd4 --- /dev/null +++ b/src/test/ui/suggestions/suggest-box.fixed @@ -0,0 +1,8 @@ +// run-rustfix + +fn main() { + let _x: Box<dyn Fn() -> Result<(), ()>> = Box::new(|| { //~ ERROR mismatched types + Err(())?; + Ok(()) + }); +} diff --git a/src/test/ui/suggestions/suggest-box.rs b/src/test/ui/suggestions/suggest-box.rs new file mode 100644 index 00000000000..e680a61db3b --- /dev/null +++ b/src/test/ui/suggestions/suggest-box.rs @@ -0,0 +1,8 @@ +// run-rustfix + +fn main() { + let _x: Box<dyn Fn() -> Result<(), ()>> = || { //~ ERROR mismatched types + Err(())?; + Ok(()) + }; +} diff --git a/src/test/ui/suggestions/suggest-box.stderr b/src/test/ui/suggestions/suggest-box.stderr new file mode 100644 index 00000000000..50c106d63a0 --- /dev/null +++ b/src/test/ui/suggestions/suggest-box.stderr @@ -0,0 +1,24 @@ +error[E0308]: mismatched types + --> $DIR/suggest-box.rs:4:47 + | +LL | let _x: Box<dyn Fn() -> Result<(), ()>> = || { + | _______________________________________________^ +LL | | Err(())?; +LL | | Ok(()) +LL | | }; + | |_____^ expected struct `std::boxed::Box`, found closure + | + = note: expected type `std::boxed::Box<dyn std::ops::Fn() -> std::result::Result<(), ()>>` + found type `[closure@$DIR/suggest-box.rs:4:47: 7:6]` + = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html +help: store this in the heap by calling `Box::new` + | +LL | let _x: Box<dyn Fn() -> Result<(), ()>> = Box::new(|| { +LL | Err(())?; +LL | Ok(()) +LL | }); + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/suggest-closure-return-type-1.rs b/src/test/ui/suggestions/suggest-closure-return-type-1.rs new file mode 100644 index 00000000000..910f273b972 --- /dev/null +++ b/src/test/ui/suggestions/suggest-closure-return-type-1.rs @@ -0,0 +1,3 @@ +fn main() { + let _v = || -> _ { [] }; //~ ERROR type annotations needed for the closure +} diff --git a/src/test/ui/suggestions/suggest-closure-return-type-1.stderr b/src/test/ui/suggestions/suggest-closure-return-type-1.stderr new file mode 100644 index 00000000000..de2d29f1270 --- /dev/null +++ b/src/test/ui/suggestions/suggest-closure-return-type-1.stderr @@ -0,0 +1,13 @@ +error[E0282]: type annotations needed for the closure `fn() -> [_; 0]` + --> $DIR/suggest-closure-return-type-1.rs:2:24 + | +LL | let _v = || -> _ { [] }; + | ^^ cannot infer type +help: give this closure an explicit return type without `_` placeholders + | +LL | let _v = || -> [_; 0] { [] }; + | ^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/suggestions/suggest-closure-return-type-2.rs b/src/test/ui/suggestions/suggest-closure-return-type-2.rs new file mode 100644 index 00000000000..6955b37ad97 --- /dev/null +++ b/src/test/ui/suggestions/suggest-closure-return-type-2.rs @@ -0,0 +1,3 @@ +fn main() { + let _v = || { [] }; //~ ERROR type annotations needed for the closure +} diff --git a/src/test/ui/suggestions/suggest-closure-return-type-2.stderr b/src/test/ui/suggestions/suggest-closure-return-type-2.stderr new file mode 100644 index 00000000000..9dbd822fbb5 --- /dev/null +++ b/src/test/ui/suggestions/suggest-closure-return-type-2.stderr @@ -0,0 +1,13 @@ +error[E0282]: type annotations needed for the closure `fn() -> [_; 0]` + --> $DIR/suggest-closure-return-type-2.rs:2:19 + | +LL | let _v = || { [] }; + | ^^ cannot infer type +help: give this closure an explicit return type without `_` placeholders + | +LL | let _v = || -> [_; 0] { [] }; + | ^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/suggestions/suggest-closure-return-type-3.rs b/src/test/ui/suggestions/suggest-closure-return-type-3.rs new file mode 100644 index 00000000000..ec6c094027e --- /dev/null +++ b/src/test/ui/suggestions/suggest-closure-return-type-3.rs @@ -0,0 +1,3 @@ +fn main() { + let _v = || []; //~ ERROR type annotations needed for the closure +} diff --git a/src/test/ui/suggestions/suggest-closure-return-type-3.stderr b/src/test/ui/suggestions/suggest-closure-return-type-3.stderr new file mode 100644 index 00000000000..ad0d4e41f78 --- /dev/null +++ b/src/test/ui/suggestions/suggest-closure-return-type-3.stderr @@ -0,0 +1,13 @@ +error[E0282]: type annotations needed for the closure `fn() -> [_; 0]` + --> $DIR/suggest-closure-return-type-3.rs:2:17 + | +LL | let _v = || []; + | ^^ cannot infer type +help: give this closure an explicit return type without `_` placeholders + | +LL | let _v = || -> [_; 0] { [] }; + | ^^^^^^^^^^^ ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/symbol-names/impl1.rs b/src/test/ui/symbol-names/impl1.rs index 52bb118fa23..137b72dcd9c 100644 --- a/src/test/ui/symbol-names/impl1.rs +++ b/src/test/ui/symbol-names/impl1.rs @@ -64,9 +64,9 @@ fn main() { //[legacy]~^ ERROR symbol-name(_ZN198_$LT$$u5b$$RF$dyn$u20$impl1..Foo$u2b$Assoc$u20$$u3d$$u20$extern$u20$$u22$C$u22$$u20$fn$LP$$RF$u8$RP$$u2b$impl1..AutoTrait$u3b$$u20$_$u5d$$u20$as$u20$impl1..main..$u7b$$u7b$closure$u7d$$u7d$..Bar$GT$6method //[legacy]~| ERROR demangling(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8)+impl1::AutoTrait; _] as impl1::main::{{closure}}::Bar>::method //[legacy]~| ERROR demangling-alt(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8)+impl1::AutoTrait; _] as impl1::main::{{closure}}::Bar>::method) - //[v0]~^^^^ ERROR symbol-name(_RNvXNCNvCs4fqI2P2rA04_5impl14mains_0ARDNtB6_3Foop5AssocFG0_KCRL0_hEuNtB6_9AutoTraitEL_j3_NtB2_3Bar6method) - //[v0]~| ERROR demangling(<[&dyn impl1[317d481089b8c8fe]::Foo<Assoc = for<'a, 'b> extern "C" fn(&'b u8)> + impl1[317d481089b8c8fe]::AutoTrait; 3: usize] as impl1[317d481089b8c8fe]::main::{closure#1}::Bar>::method) - //[v0]~| ERROR demangling-alt(<[&dyn impl1::Foo<Assoc = for<'a, 'b> extern "C" fn(&'b u8)> + impl1::AutoTrait; 3] as impl1::main::{closure#1}::Bar>::method) + //[v0]~^^^^ ERROR symbol-name(_RNvXNCNvCs4fqI2P2rA04_5impl14mains_0ARDNtB6_3Foop5AssocFG_KCRL0_hEuNtB6_9AutoTraitEL_j3_NtB2_3Bar6method) + //[v0]~| ERROR demangling(<[&dyn impl1[317d481089b8c8fe]::Foo<Assoc = for<'a> extern "C" fn(&'a u8)> + impl1[317d481089b8c8fe]::AutoTrait; 3: usize] as impl1[317d481089b8c8fe]::main::{closure#1}::Bar>::method) + //[v0]~| ERROR demangling-alt(<[&dyn impl1::Foo<Assoc = for<'a> extern "C" fn(&'a u8)> + impl1::AutoTrait; 3] as impl1::main::{closure#1}::Bar>::method) #[rustc_def_path] //[legacy]~^ ERROR def-path(<[&dyn Foo<Assoc = for<'r> extern "C" fn(&'r u8)> + AutoTrait; _] as main::{{closure}}#1::Bar>::method) //[v0]~^^ ERROR def-path(<[&dyn Foo<Assoc = for<'r> extern "C" fn(&'r u8)> + AutoTrait; _] as main::{{closure}}#1::Bar>::method) diff --git a/src/test/ui/symbol-names/impl1.v0.stderr b/src/test/ui/symbol-names/impl1.v0.stderr index 1c4b256c9e9..e024799df86 100644 --- a/src/test/ui/symbol-names/impl1.v0.stderr +++ b/src/test/ui/symbol-names/impl1.v0.stderr @@ -46,19 +46,19 @@ error: def-path(bar::<impl foo::Foo>::baz) LL | #[rustc_def_path] | ^^^^^^^^^^^^^^^^^ -error: symbol-name(_RNvXNCNvCs4fqI2P2rA04_5impl14mains_0ARDNtB6_3Foop5AssocFG0_KCRL0_hEuNtB6_9AutoTraitEL_j3_NtB2_3Bar6method) +error: symbol-name(_RNvXNCNvCs4fqI2P2rA04_5impl14mains_0ARDNtB6_3Foop5AssocFG_KCRL0_hEuNtB6_9AutoTraitEL_j3_NtB2_3Bar6method) --> $DIR/impl1.rs:63:13 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(<[&dyn impl1[317d481089b8c8fe]::Foo<Assoc = for<'a, 'b> extern "C" fn(&'b u8)> + impl1[317d481089b8c8fe]::AutoTrait; 3: usize] as impl1[317d481089b8c8fe]::main::{closure#1}::Bar>::method) +error: demangling(<[&dyn impl1[317d481089b8c8fe]::Foo<Assoc = for<'a> extern "C" fn(&'a u8)> + impl1[317d481089b8c8fe]::AutoTrait; 3: usize] as impl1[317d481089b8c8fe]::main::{closure#1}::Bar>::method) --> $DIR/impl1.rs:63:13 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling-alt(<[&dyn impl1::Foo<Assoc = for<'a, 'b> extern "C" fn(&'b u8)> + impl1::AutoTrait; 3] as impl1::main::{closure#1}::Bar>::method) +error: demangling-alt(<[&dyn impl1::Foo<Assoc = for<'a> extern "C" fn(&'a u8)> + impl1::AutoTrait; 3] as impl1::main::{closure#1}::Bar>::method) --> $DIR/impl1.rs:63:13 | LL | #[rustc_symbol_name] diff --git a/src/test/ui/symbol-names/issue-60925.legacy.stderr b/src/test/ui/symbol-names/issue-60925.legacy.stderr index 7fcd2ede31b..de8efdde737 100644 --- a/src/test/ui/symbol-names/issue-60925.legacy.stderr +++ b/src/test/ui/symbol-names/issue-60925.legacy.stderr @@ -4,13 +4,13 @@ error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3f LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(issue_60925::foo::Foo<issue_60925::llv$u6d$..Foo$GT$::foo::h059a991a004536ad) +error: demangling(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo::h059a991a004536ad) --> $DIR/issue-60925.rs:21:9 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling-alt(issue_60925::foo::Foo<issue_60925::llv$u6d$..Foo$GT$::foo) +error: demangling-alt(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo) --> $DIR/issue-60925.rs:21:9 | LL | #[rustc_symbol_name] diff --git a/src/test/ui/symbol-names/issue-60925.rs b/src/test/ui/symbol-names/issue-60925.rs index 89de15cc0f3..02438351dbc 100644 --- a/src/test/ui/symbol-names/issue-60925.rs +++ b/src/test/ui/symbol-names/issue-60925.rs @@ -20,8 +20,8 @@ mod foo { impl Foo<::llvm::Foo> { #[rustc_symbol_name] //[legacy]~^ ERROR symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo - //[legacy]~| ERROR demangling(issue_60925::foo::Foo<issue_60925::llv$u6d$..Foo$GT$::foo - //[legacy]~| ERROR demangling-alt(issue_60925::foo::Foo<issue_60925::llv$u6d$..Foo$GT$::foo) + //[legacy]~| ERROR demangling(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo + //[legacy]~| ERROR demangling-alt(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo) //[v0]~^^^^ ERROR symbol-name(_RNvMNtCs4fqI2P2rA04_11issue_609253fooINtB2_3FooNtNtB4_4llvm3FooE3foo) //[v0]~| ERROR demangling(<issue_60925[317d481089b8c8fe]::foo::Foo<issue_60925[317d481089b8c8fe]::llvm::Foo>>::foo) //[v0]~| ERROR demangling-alt(<issue_60925::foo::Foo<issue_60925::llvm::Foo>>::foo) diff --git a/src/test/ui/traits/traits-conditional-model-fn.rs b/src/test/ui/traits/traits-conditional-model-fn.rs index 27ce6d93a81..ba88670032c 100644 --- a/src/test/ui/traits/traits-conditional-model-fn.rs +++ b/src/test/ui/traits/traits-conditional-model-fn.rs @@ -6,7 +6,6 @@ // aux-build:go_trait.rs - extern crate go_trait; use go_trait::{Go, GoMut, GoOnce, go, go_mut, go_once}; @@ -14,8 +13,6 @@ use go_trait::{Go, GoMut, GoOnce, go, go_mut, go_once}; use std::rc::Rc; use std::cell::Cell; -/////////////////////////////////////////////////////////////////////////// - struct SomeGoableThing { counter: Rc<Cell<isize>> } @@ -26,8 +23,6 @@ impl Go for SomeGoableThing { } } -/////////////////////////////////////////////////////////////////////////// - struct SomeGoOnceableThing { counter: Rc<Cell<isize>> } @@ -38,8 +33,6 @@ impl GoOnce for SomeGoOnceableThing { } } -/////////////////////////////////////////////////////////////////////////// - fn main() { let counter = Rc::new(Cell::new(0)); let mut x = SomeGoableThing { counter: counter.clone() }; diff --git a/src/test/ui/type/type-params-in-different-spaces-1.rs b/src/test/ui/type/type-params-in-different-spaces-1.rs index 449a26e901d..71fb7f380ae 100644 --- a/src/test/ui/type/type-params-in-different-spaces-1.rs +++ b/src/test/ui/type/type-params-in-different-spaces-1.rs @@ -5,7 +5,7 @@ trait BrokenAdd: Copy + Add<Output=Self> { *self + rhs //~ ERROR mismatched types //~| expected type `Self` //~| found type `T` - //~| expected Self, found type parameter + //~| expected type parameter, found a different type parameter } } diff --git a/src/test/ui/type/type-params-in-different-spaces-1.stderr b/src/test/ui/type/type-params-in-different-spaces-1.stderr index b3b78424fd9..0448a28ea8e 100644 --- a/src/test/ui/type/type-params-in-different-spaces-1.stderr +++ b/src/test/ui/type/type-params-in-different-spaces-1.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/type-params-in-different-spaces-1.rs:5:17 | LL | *self + rhs - | ^^^ expected Self, found type parameter + | ^^^ expected type parameter, found a different type parameter | = note: expected type `Self` found type `T` diff --git a/src/test/ui/type/type-params-in-different-spaces-3.stderr b/src/test/ui/type/type-params-in-different-spaces-3.stderr index 4e8134da2dd..e25f79947c7 100644 --- a/src/test/ui/type/type-params-in-different-spaces-3.stderr +++ b/src/test/ui/type/type-params-in-different-spaces-3.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | fn test<X>(u: X) -> Self { | ---- expected `Self` because of return type LL | u - | ^ expected Self, found type parameter + | ^ expected type parameter, found a different type parameter | = note: expected type `Self` found type `X` diff --git a/src/tools/cargo b/src/tools/cargo -Subproject e853aa976543168fbb6bfcc983c35c3facca984 +Subproject 3f700ec43ce72305eb5315cfc710681f3469d4b diff --git a/src/tools/clippy b/src/tools/clippy -Subproject 72da1015d6d918fe1b29170acbf486d30e0c269 +Subproject cd3df6bee0ee07c7dbb562b29576a0b513a4331 diff --git a/src/tools/miri b/src/tools/miri -Subproject c1cb24969e84dfaded2769ab5575effc8d4f5c3 +Subproject 4f6f264c305ea30f1de90ad0c2f341e84d972b2 diff --git a/src/tools/rls b/src/tools/rls -Subproject 7b0a20bf13b7061b1eb31a058117ac5517ff8cc +Subproject 496c89275221303a4b0c2779cb8203fb3ce2a13 |
